Make GTK Entry box smaller - gtk

I am trying to make a GUI program in Julia using Gtk. My program includes a large number of GtkEntry boxes. However, I am running into space issues because the Entry boxes have a lot of internal padding around the actual characters. I would like to reduce, at least, the top and bottom whitespace. I have tried to use the setproperty!() function to change the height-request value, but that seems to be only able to make the box bigger, not smaller. Additionally, the margin, margin-top, etc. fields are all set to 0 by default. Again, I can make them bigger but not smaller.
Is this possible to fix? I have included below a minimal working example, a screenshot, and a Julia REPL output displaying the available properties.
Edit:
I have also tried using a css file (test.css) with the contents
entry {
margin-top: 0;
margin-bottom: 0;
padding-top: 0;
padding-bottom: 0;
}
Julia 0.6.0 code:
using Gtk
win = GtkWindow("Example")
sb = GtkGrid()
function sb_entry(label)
frame = GtkFrame(label)
entry = GtkEntry()
setproperty!(entry, :input_purpose, 2)
push!(frame, entry)
return frame
end
sb_rows = sb_entry("rows")
sb_cols = sb_entry("cols")
sb_row_off = sb_entry("row off")
sb_col_off = sb_entry("col off")
sb[1,1] = sb_rows
sb[2,1] = sb_cols
sb[1,2] = sb_row_off
sb[2,2] = sb_col_off
setproperty!(sb, :column_homogeneous, true)
setproperty!(sb, :column_spacing, 5)
setproperty!(sb, :row_spacing, 5)
push!(win, sb)
### begin edit (css)
screen = Gtk.GAccessor.screen(win)
provider = GtkCssProviderLeaf(filename="/path/to/test.css")
ccall((:gtk_style_context_add_provider_for_screen, Gtk.libgtk), Void,
(Ptr{Void}, Ptr{GObject}, Cuint),
screen, provider, 1)
### end edit (css)
showall(win)
if !isinteractive()
c = Condition()
signal_connect(win, :destroy) do widget
notify(c)
end
wait(c)
end
julia> sb_row_off[1]
Gtk.GtkEntryLeaf(editing-canceled=FALSE, name="", parent, width-request=-1,
height-request=-1, visible=TRUE, sensitive=TRUE, app-paintable=FALSE,
can-focus=TRUE, has-focus=FALSE, is-focus=TRUE, focus-on-click=TRUE,
can-default=FALSE, has-default=FALSE, receives-default=FALSE, composite-child=FALSE,
style, events=0, no-show-all=FALSE, has-tooltip=FALSE, tooltip-markup=NULL,
tooltip-text=NULL, window, opacity=1.000000, double-buffered, halign=GTK_ALIGN_FILL,
valign=GTK_ALIGN_FILL, margin-left, margin-right, margin-start=0, margin-end=0,
margin-top=0, margin-bottom=0, margin=0, hexpand=FALSE, vexpand=FALSE,
hexpand-set=FALSE, vexpand-set=FALSE, expand=FALSE, scale-factor=2, buffer,
cursor-position=0, selection-bound=0, editable=TRUE, max-length=0, visibility=TRUE,
has-frame=TRUE, inner-border, invisible-char=9679, activates-default=FALSE,
width-chars=-1, max-width-chars=-1, scroll-offset=0, text="", xalign=0.000000,
truncate-multiline=FALSE, shadow-type, overwrite-mode=FALSE, text-length=0,
invisible-char-set=FALSE, caps-lock-warning=TRUE, progress-fraction=0.000000,
progress-pulse-step=0.100000, primary-icon-pixbuf, secondary-icon-pixbuf,
primary-icon-stock, secondary-icon-stock, primary-icon-name=NULL,
secondary-icon-name=NULL, primary-icon-gicon, secondary-icon-gicon,
primary-icon-storage-type=GTK_IMAGE_EMPTY,
secondary-icon-storage-type=GTK_IMAGE_EMPTY, primary-icon-activatable=TRUE,
secondary-icon-activatable=TRUE, primary-icon-sensitive=TRUE,
secondary-icon-sensitive=TRUE, primary-icon-tooltip-text=NULL,
secondary-icon-tooltip-text=NULL, primary-icon-tooltip-markup=NULL,
secondary-icon-tooltip-markup=NULL, im-module=NULL, placeholder-text=NULL,
completion, input-purpose=GTK_INPUT_PURPOSE_DIGITS, input-hints=GTK_INPUT_HINT_NONE,
attributes, populate-all=FALSE, tabs)

entry { min-height: 0px; } allows it to be as small as possible. Adjust size as required.

Related

how to get rid of padding around Gtk.Image in Gtk.Box / Gtk.Grid in gtk4?

I'm trying to write a simple GUI using Gtk4 (in Python), but I'm having trouble with getting rid of padding (and I don't understand why the padding is there).
The goal is pretty simple - I need a Gtk.Grid showing a bunch of images with some basic metadata. AFAICS a good way to do that is Window -> ScrollWindow -> Grid -> Box -> (Image + Label). And in general this works, except that the images have a lot of top/bottom padding, so the labels have a lot of empty space around, which I don't like but can't get rid of it :-(
See this screenshot
Here's a simple example demonstrating this:
import gi
import sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, GdkPixbuf
def create_image(file_name, img_width, cssProvider = None):
info = 'file:' + file_name
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
# box.get_style_context().add_provider(cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
# box.add_css_class('thumbnail')
box.set_hexpand(True)
# add image to top
pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_name)
# calculate height to keep width and aspect ratio
img_height = pixbuf.get_height() * img_width / pixbuf.get_width()
image = Gtk.Image.new_from_pixbuf(pixbuf)
image.set_size_request(img_height, img_width)
# image.get_style_context().add_provider(cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
# image.add_css_class('thumbnail-image')
box.append(image)
# add label to bottom
label = Gtk.Label(label=info)
# label.get_style_context().add_provider(cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
# label.add_css_class('thumbnail-label')
box.append(label)
return box
class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cssProvider = None
# self.cssProvider = Gtk.CssProvider()
# self.cssProvider.load_from_data(b"""
#.thumbnail {background-color: white; color: black; border: 1px solid #ddd; margin: 5px; padding: 0; }
#.thumbnail-label { font-size: 12pt; margin: 0; padding: 0; }
#.thumbnail-image { margin: 0; padding: 0; }
#.green { background-color: #bfb; }""")
self.set_default_size(900, 600)
self.set_title("MyApp")
self.grid = Gtk.Grid()
self.window = Gtk.ScrolledWindow()
self.window.set_child(self.grid)
self.set_child(self.window)
idx = 0
prev = None
for idx in range(0,20):
# 4 columns
i = int(idx / 4)
j = int(idx % 4)
image = create_image('frog.jpg', 1920/4 - 10, self.cssProvider)
self.grid.attach(image, j, i, 1, 1)
class MyApp(Gtk.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
self.win = MainWindow(application=app)
self.win.present()
app = MyApp(application_id="com.example.GtkApplication")
app.run(sys.argv)
This needs an image called 'frog.jpg', e.g. this one.
The sizes are meant to work on 1920x1080, with 4 columns. I'm sure it could be done more dynamic (i.e. to work better with resized windows etc.), but I believe that's a separate issue.
I've tried a bunch of things, including styling using CSS, etc. (which is commented-out in the sample).
I also experimented with setting hexpand/vexpand on different widgets, not adding the label, and various similar things.
Apparently using Gtk.Picture instead of Gtk.Image solves the issue - with Picture there's no unwanted empty space/padding. Seems a bit confusing, considering Picture/Image are often used as synonyms. Maybe it's in the gtk docs somewhere, but I don't see it - certainly not without reading between the lines. I see some discussion of "natural size" but I don't see how'd that imply this behavior. Anyway, if others face the same issue, try using Gtk.Picture.

leaflet map does not appear correctly until resize

I am using Leaflet with scalajs-leaflet facade on Binding.scala, and the map initializes/appears incorrectly.
In order to reproduce the issue, i have prepared a lihaoyi/workbench page similar to that in scalajs-leaflet.
First, download the forked scalajs-leaflet from https://github.com/mcku/scalajs-leaflet
Run sbt in scalajs-leaflet directory.
Enter ~ example/fastOptJS in sbt. Now, a web server started at port 12345.
Open
http://localhost:12345/example/target/scala-2.12/classes/leaflet2binding-dev.html in a browser
The problem is the map container appears but the content (tiles, etc) is not correct. Map becomes fine after a small resize on window, which triggers _onResize handler of leaflet.
The container is in the Leaflet2Binding.scala file and has its size already specified prior to initialization:
val mapElement = <div id="mapid" style="width: 1000px; height: 600px;
position: relative; outline: currentcolor none medium;"
class="leaflet-container leaflet-touch leaflet-fade-anim
leaflet-grab leaflet-touch-drag leaflet-touch-zoom"
data:tabindex="0"></div>.asInstanceOf[HTMLElement]
It is possible to insert a line lmap.invalidateSize(true) in the following line before returning the element
https://github.com/mcku/scalajs-leaflet/blob/83b770bc76de450567ababf6c7d2af0700dd58c9/example/src/main/scala/example/Leaflet2Binding.scala#L39, but did not help in this case. Namely here:
#dom def renderMap = {
val mapElement = ... (same element as above)
.. some other initializations ..
lmap.invalidateSize(true) // true means, use animation
println("mapElement._leaflet_id " +mapElement.asInstanceOf[js.Dynamic]._leaflet_id) // prints non-null value, makes me think the container is initialized
mapElement
}
Any ideas? This is binding.scala specific, but it may be a leaflet issue as well.
EDIT Possible workaround
It looks like, the map element has its clientWidth property not available during the process. Which is understandable as the document is not "ready" yet. However, the css style.width is available and could be defined in px. In that case it is possible to patch leaflet to take css style width into account during computation.
it works if the style width is specified in px.
diff --git a/src/map/Map.js b/src/map/Map.js
index b94dd443..6544d7b7 100644
--- a/src/map/Map.js
+++ b/src/map/Map.js
## -903,8 +903,9 ## export var Map = Evented.extend({
getSize: function () {
if (!this._size || this._sizeChanged) {
this._size = new Point(
- this._container.clientWidth || 0,
- this._container.clientHeight || 0);
+
+ this._container.clientWidth || parseInt(this._container.style.width.replace("px",""),10) || 0,^M
+ this._container.clientHeight || parseInt(this._container.style.height.replace("px",""),10) || 0);;^M
this._sizeChanged = false;
}
Maybe lmap.invalidateSize(true) is called too early (DOM is not ready or repainted).
Make sure this does not happen. To prevent that I wrap this code like:
setTimeout(function () {
mapid.invalidateSize(true);
}, 100);
This must be done after every DOM repaint.
People that are still facing this issue for react-leaflet, making the component only render when zoom and center are initiated, and removed when the Map is not displaying:
useEffect(() => {
setCenter([50.5, 30.5]);
setZoom(14);
}, []);
And then in the JSX
{zoom && center.length > 0 && (
<div className={styles.map}>
<Map center={center} zoom={zoom} />
</div>
)}

Styling list row with CSS in GTK+3

My Python app has a ListBox with some placeholder rows in them right now.
for i in range(0, 10):
myListRow = Gtk.ListBoxRow()
myList.add(myListRow)
myListItem = Gtk.Box(name="MyListItem", orientation=Gtk.Orientation.HORIZONTAL)
myListRow.add(Gtk.Label(label="placeholder"))
I'm running into a tonne of trouble styling the rows in any way. Using an arbitrary background colour, none of these result in any changes:
.list row {
background: #f00;
}
-
.row {
background: #f00;
}
-
row {
background: #f00;
}
-
GtkListBox row {
background: #f00;
}
For some reason, this does, though, and only with the area of the ListBox that has labels in it:
.list > * {
background: #f00;
}
Testing with .list .label { background: #0f0 } confirms that it's not just styling the labels. The rows are certainly in the ListBox and can certainly be styled, but I do not have any idea what the CSS selectors for those ListBox rows might be. Any help would be appreciated.
Using PyGI running GTK+3.18 in Python 3.4.
I forced the GTK debugger/inspector to run by adding "GTK_DEBUG" into my System Variables with the value "interactive" to look.
The name of the row element is actually list-row.

GTK+ Css ignoring margin [duplicate]

How can i make layout like this using CSS stylesheet for GTK app?
Here is example code:
#!/usr/bin/python
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
from gi.repository import Gtk, Gdk
# Main application window
# =======================
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect("delete-event", Gtk.main_quit)
self.set_name("main-window")
# load style from file
cssProvider = Gtk.CssProvider()
cssProvider.load_from_path('style.css')
# get the default screen for the default display
screen = Gdk.Screen.get_default()
# new object which will store styling information affecting widget
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
self.resize(200, 200)
# create box for another boxes
self.box = Gtk.Box()
self.box.set_name("box")
self.add(self.box)
self.box2 = Gtk.Box()
self.box2.set_name("box2")
self.box.pack_start(self.box2, False, False, 0)
self.text = Gtk.Label.new()
self.text.set_text('text')
self.box2.pack_start(self.text, False, False, 0)
self.box3 = Gtk.Box()
self.box3.set_name("box3")
self.box.pack_start(self.box3, False, False, 0)
self.text2 = Gtk.Label.new()
self.text2.set_text('text2')
self.box3.pack_start(self.text2, False, False, 0)
# Create and show window
win = MainWindow()
win.show_all()
Gtk.main()
Here is CSS stylesheet for this which will work in HTML
#box {
background: blue;
padding: 5px;
}
#box2 {
background: red;
margin: 5px;
}
#box3 {
background: green;
margin: 5px;
}
But result is:
Of course I can add padding/spacing values in python code, but only for horizontal gaps without nesting boxes. Can it be done without hardcoding, with css-only solution?
Not right now. GTK doesn't support margin properties on its widgets, and it only supports padding properties on widgets that draw a frame. (Which elements draw a frame can be a bit arbitrary, but Gtk.Box and Gtk.Label don't, so that's why your example doesn't work. You can fake it on any widget by putting it inside a Gtk.Frame though.)
This blog post reveals that margin and padding are planned to be supported consistently on all widgets in the upcoming GTK 3.20.

Remove space from Ui widgets that are not visible

function doGet() {
var app = UiApp.createApplication();
var flex = app.createFlexTable();
for (var i = 1; i<=30; i++)
flex.setWidget(i, 0, app.createButton('Button '+i).setId('Button'+i).setVisible(false));
app.getElementById('Button1').setVisible(true);
var submit = app.createButton('Submit');
app.add(flex).add(submit);
return app;
}
Produces this Ui.
How can we eliminate the empty space between the first visible button and the 'Submit' button?
The space is coming from the browser specific styling of the various HTML elements, which applies, for example, a 2px border-spacing to each hidden row. (I'm testing in Chrome; it may be different for other browsers.)
I'd suggest using a CSS reset to clear out all browser-specific styling. A simple one like this fixes your spacing issue (again, in Chrome):
div, table, tbody, tr, td {
margin: 0;
padding: 0;
border-spacing: 0;
border-collapse: collapse;
}