{"id":1468,"date":"2014-09-06T22:04:20","date_gmt":"2014-09-06T20:04:20","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=1468"},"modified":"2014-09-06T22:04:20","modified_gmt":"2014-09-06T20:04:20","slug":"tamano-constante-en-gtk","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=1468","title":{"rendered":"Tama\u00f1o constante en GTK"},"content":{"rendered":"<p>Hace unos d\u00edas envi\u00e9 un parche para <a href=\"https:\/\/launchpad.net\/slingshot\" target=\"_blank\">Slingshot<\/a>, el lanzador de aplicaciones de <a href=\"http:\/\/elementaryos.org\/\" target=\"_blank\">Elementary OS<\/a>. El problema que ten\u00eda es que ten\u00eda fijados al pixel los tama\u00f1os de todos los elementos. Esto se adapta bien si se utiliza el tema de Elementary y, adem\u00e1s, en lengua inglesa. Sin embargo, en el momento en que se utiliza otro tema, o bien una lengua en la que alguna categor\u00eda de programas sea mucho m\u00e1s larga que en ingl\u00e9s, nos encontraremos con que el conjunto de iconos queda recortado por la derecha:<\/p>\n<p><a href=\"http:\/\/www.rastersoft.com\/blogpic\/slingshot_size_bug.png\" rel=\"lightbox-0\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/www.rastersoft.com\/blogpic\/slingshot_size_bug.png\" alt=\"\" width=\"783\" height=\"698\" \/><\/a><\/p>\n<p>Se supone que esto no deber\u00eda ocurrir porque Gtk permite crear interfaces que se redimensionen de manera autom\u00e1tica, sin embargo en slingshot esto no ocurr\u00eda. El motivo es que los iconos no est\u00e1n hechos con un Gtk.IconView, sino con botones dentro de un Gtk.Grid. Pero los autores quer\u00edan, adem\u00e1s, que dichos botones tuviesen un tama\u00f1o fijo de 130&#215;130 pixels exactamente, por lo que la \u00fanica idea que se les ocurri\u00f3 fue fijar el tama\u00f1o exacto de la ventana que contiene todo el lanzador, incluyendo la lista de categor\u00edas, el buscador, etc. El motivo de hacerlo as\u00ed es que dentro de cada bot\u00f3n hay, adem\u00e1s del icono, una etiqueta con el nombre de la aplicaci\u00f3n, y salvo que el contenedor tenga un tama\u00f1o determinado, la etiqueta intentar\u00e1 expandirse todo lo que pueda, y ni siquiera sirve de nada pedir un tama\u00f1o deseado, porque si el texto en la etiqueta es m\u00e1s largo, la etiqueta se expandir\u00e1 todo lo que pueda para contener todo el texto.<\/p>\n<p>La primera idea que se me ocurri\u00f3 fue engancharme a la se\u00f1al <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Widget.size_allocate\" target=\"_blank\">size_allocate<\/a> del bot\u00f3n. Esta se\u00f1al se emite cada vez que un widget cambia de tama\u00f1o por el motivo que sea, y recibe como par\u00e1metro sus nuevas medidas. Con ella y la propiedad <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Label.max_width_chars\" target=\"_blank\">max_width_chars<\/a> intent\u00e9 limitar el tama\u00f1o de la etiqueta para que el bot\u00f3n tuviese el tama\u00f1o m\u00e1ximo deseado; por desgracia era un proceso relativamente lento y que, adem\u00e1s, provocaba un parpadeo en la ventana, pues \u00e9sta primero tomaba el valor m\u00e1ximo y se reduc\u00eda progresivamente hasta el tama\u00f1o correcto, a medida que las distintas etiquetas iban reduciendo su n\u00famero de caracteres.<\/p>\n<p>La segunda idea, sugerida por la gente de la lista de desarrollo de Gtk, fue encapsular la etiqueta dentro de un <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Fixed\" target=\"_blank\">Gtk.Fixed<\/a>, pues permite ajustar manualmente el tama\u00f1o de cualquier widget situado en su interior. Esta soluci\u00f3n <em>casi<\/em> funcion\u00f3, pues aunque la etiqueta se manten\u00eda en el ancho deseado, el Gtk.Fixed contenedor se redimensionaba hasta ocupar el mismo espacio que ocupar\u00eda la etiqueta si estaba sola.<\/p>\n<p>Ante esto me di cuenta de que la soluci\u00f3n iba a necesitar de algo m\u00e1s de investigaci\u00f3n y, sobre todo, de meterme en los entresijos del renderizado de Gtk, as\u00ed que empec\u00e9 a investigar, y descubr\u00ed que todo <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Widget\" target=\"_blank\">widget<\/a> tiene dos m\u00e9todos que participan de manera especial en la asignaci\u00f3n de tama\u00f1o: <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Widget.get_preferred_width\" target=\"_blank\">get_preferred_width<\/a> y <a href=\"http:\/\/valadoc.org\/#!api=gtk+-3.0\/Gtk.Widget.get_preferred_height\" target=\"_blank\">get_preferred_height<\/a>. Estos dos m\u00e9todos devuelven dos valores: el primero es el tama\u00f1o m\u00ednimo que necesita dicho widget en el eje correspondiente para mostrar su contenido, y el segundo el tama\u00f1o deseado. En el caso de una etiqueta, el tama\u00f1o deseado ser\u00e1 el ancho que ocupe la totalidad del texto puesto en una \u00fanica l\u00ednea, mientras que el tama\u00f1o m\u00ednimo depender\u00e1 de varias opciones: si no hay elipsis de texto coincidir\u00e1 con el tama\u00f1o deseado, pero si no, ser\u00e1 menor, de lo necesario para pintar el borde y unos puntos suspensivos.<\/p>\n<p>Cuando un contenedor tiene en su interior otro widget, llama a estos dos m\u00e9todos para saber cuanto espacio debe reservar. Lo interesante es que dichos valores son, realmente, orientativos, pues el contenedor puede asignar otros tama\u00f1os si as\u00ed lo considera oportuno. As\u00ed, si una etiqueta pide 100 pixels pero est\u00e1 en una ventana que mide 200 y tiene activo el flag de expandirse, el tama\u00f1o final de la etiqueta ser\u00e1 de 200. De igual forma, si una etiqueta pide un tama\u00f1o deseado de 100 pixels de ancho pero la ventana mide 50, recibir\u00e1 50 y el texto tendr\u00e1 que ocupar varias l\u00edneas.<\/p>\n<p>Ante esto se me ocurri\u00f3 probar qu\u00e9 ocurrir\u00eda si creo una nueva clase que herede de Gtk.Label, en la que redefino (<em>override<\/em>) el m\u00e9todo <em>get_preferred_width<\/em> para que devuelva 120 como ancho m\u00ednimo y deseado (porque cada bot\u00f3n tiene un margen de 5 pixels por cada lado). El resultado es justo el deseado: la etiqueta mide exactamente el ancho que se le indica, y aplica las reglas para pasar a nuevas l\u00edneas o para a\u00f1adir elipsis.<\/p>\n<p>Por supuesto esto es f\u00e1cil de hacer en Vala; en C es posible hacerlo tambi\u00e9n, pero obliga a meterse en el interior de GObject, una tarea que, sinceramente, no me llama demasiado en este momento.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hace unos d\u00edas envi\u00e9 un parche para Slingshot, el lanzador de aplicaciones de Elementary OS. El problema que ten\u00eda es que ten\u00eda fijados al pixel los tama\u00f1os de todos los elementos. Esto se adapta bien si se utiliza el tema de Elementary y, adem\u00e1s, en lengua inglesa. Sin embargo, en el momento en que se &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=1468\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Tama\u00f1o constante en GTK<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,6],"tags":[],"class_list":["post-1468","post","type-post","status-publish","format-standard","hentry","category-programacion","category-trucos"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/1468","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1468"}],"version-history":[{"count":0,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/1468\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1468"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1468"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1468"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}