GtkButton with Image- align to left - gtk

I am creating a button with image on it. I would like to get it aligned left and NO GAP from margin of the button. However alhtough I aligned my button to the left of the text, there is a small "fixed" amount of gap between the image and the button border. How can I zero the gap?
Here is the code:
GtkWidget *button;
GtkWidget *buttonImage;
GtkSettings *default_settings = gtk_settings_get_default();
g_object_set(default_settings, "gtk-button-images", TRUE, NULL);
buttonImage = gtk_image_new();
gtk_image_set_from_file(GTK_IMAGE(buttonImage),"icon.jpg");
button= gtk_button_new_with_label("Click");
gtk_button_set_relief ((GtkButton *)button, GTK_RELIEF_NONE);
gtk_button_set_image((GtkButton *)button, buttonImage);
gtk_button_set_image_position((GtkButton *)button, GTK_POS_LEFT);
thank you.

There is likely some padding and/or border space being added by the theme. This gets complicated as different users may have different themes for different reasons. So it's often a good idea to leave these theme-specific settings as they are. That being said, there are situations in which you need to override these settings. For example, a text editor has tabs which have a GtkButton with a GTK_STOCK_CLOSE button. This button needs to have all padding and borders removed so that it is just the size of it's image. You can adapt this technique for your needs.
In GTK+3 this can done with GtkCssProvider and GtkStyleContext.
const gchar data[] = * { "
"-GtkButton-default-border : 0; "
"-GtkButton-default-outside-border : 0; "
"-GtkButton-inner-border: 0; "
"-GtkWidget-focus-line-width : 0; "
"-GtkWidget-focus-padding : 0; "
"padding: 0; "
"}";
context = gtk_widget_get_style_context (GTK_WIDGET(button));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, data, -1, NULL);
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
That code might not be quite right, but, it should point you in the right direction. I've only implemented this technique in Python.
If you're developing for GTK+ 2, the way I used to do this was by calling calling gtk_widget_set_size_request() in a callback function to the "style-set" signal of the GtkButton.

Related

Growing menu with scrollbar

I hate to ask such a generic question but I'm really stuck and super hoping someone can help me along the way. Here is the situation:
I'm making the GUI for a mobile app, portrait mode. I'm using canvas scalers to scale my canvasses with a reference width of 1080. This means I effectively don't know the height of my screen space.
What I want to create is a menu with a variable amount of items. The menu must be anchored to the bottom (with an offset margin) and grow upwards. So far I've been able to manage this using VerticalLayoutGroup and anchoring the rect transform to the bottom.
But my last requirement is that if the content would grow too big, a scrollbar would appear. The definition of the content being too big is: if it would extend the (unknown) screen height ( minus the offset margin of course). I hope the following image illustrates this much clearer:
I have a unity project here: https://ufile.io/v31br
Did you give a try to scrollView? here it is: https://unity3d.com/learn/tutorials/topics/user-interface-ui/scroll-view
You can use your vertical layout inside it and you will probably want to deactivate horizontal scroll and delete the horizontal slider.
Via script you can check its rectTransform height and compare it to your container's size, when reached maxHeight you can start managing your item's sizes
I assume you use the ScrollRect component as it is the right component to use in your case.
You can check the screen height with the Screen.height property.
Once you know the screen height you can compare it with your rect height and toggle the scrollbar with the ScrollRect.vertical property. You may have to change the ScrollRect.verticalScrollbarVisibility to permanent in order to make it work for you.
The answer Dave posted was close, but the problem is that the scrollview doesn't expand. I fixed it eventually by stretching the scrollview and resizing the parent manually as items are added. I set the anchors to the maximum size and adjust the sizeDelta.
public class MenuScript : MonoBehaviour
{
public int MenuItemCount;
public GameObject MenuItemPrefab;
public Transform MenuItemParent;
private RectTransform _rectTransform;
void Start()
{
_rectTransform = GetComponent<RectTransform>();
for (var i = 0; i <= MenuItemCount; i++)
{
GameObject instance = Instantiate(MenuItemPrefab, MenuItemParent, false);
instance.GetComponent<Text>().text = instance.name = "Item " + i;
float size = instance.transform.GetComponent<RectTransform>().sizeDelta.y;
TryExpandBy(size + 10);
}
}
private void TryExpandBy(float size)
{
var deltaY = _rectTransform.sizeDelta.y + size;
if (deltaY > 0) deltaY = 0;
_rectTransform.sizeDelta = new Vector2(_rectTransform.sizeDelta.x, deltaY);
}
}

How to slide a panel from right to left using bunifuTransition in c#

I have bunifutransition1 that slides my mainpanel from left to right upon clicking showbutton. (It shows the hidden mainpanel.)
What I want is, when I click closebutton, the mainpanel will slide from right to left (to hide the mainpanel again). It seems that bunifuTransition does not have an animation that reverses the animation of VertSlide or HorizSlide.
What should I do to slide my mainpanel from right to left to hide it again on my form?
I was having the exact same issue but upon reading your question the answer finally became prevalent in my mind. The solution here is to stop using BunifuTranisition altogether and go for the good ol' for loops and the other mods, puns intended.
int originalWidth = panel.width;
int menuClicksIndex = 0;
private void beginTransition()
{
if (menuClickIndex % 2 == 0)
{
//This executes on the first click
for(int i = originalWidth-1; i>=0; i--)
{
// Loops from original width to 0
panel.Width = i;
}
}
else
{
for (int i = 0; i <= originalWidth; i++)
{
panel.Width = i;
}
}
menuClickIndex++;
}
This works for me but it glitches on the way back from left to right. So a mixed version with BunifuTransitions for the opener and the for loop for the closer would be the ideal solution here.
UPDATE 1: It seems as if while changing the width of the panel from 0 to say, 350, the content inside the panel doesn't render until the height is set to the max, but while decreasing the height from 350 to 0, the content is already rendered and so it seems smooth to close but cluttery to open, hence probably explaining why BunifuTransition is unable to do that as well.
Solution Here.
Just go bunifu transition properties
Open or dragdown DefaultAnimation. Find this option in menu ("Side Coeff") It Show value of
X and Y {X=1, Y=0} . You just change this value {X=-1, Y=0}.
Then Start your project and check. Your slider sliding left to right. :)
Keep enjoy.
Regards,
Haris Ali
Use this command: bunifuTransition1.HideSync(guna2Panel1); before any code on event button click!

GTK ignores any type of window positioning

I've been trying to position a splash screen at the center of the screen. In Windows, such a request is easy using SetWindowPos and a bit of geometric arithmetic. I found out that all requests to move a window are ignored by the windowing manager. So my question is, how come I see so many applications with pretty splash screens properly centered? I started with GTK_WINDOW_TOPLEVEL BTW and just switch to popup trying a few things. Setting the gravity and position do not fail, they are just ignored. Even defined in a .glade file, the window is ignored.
{
GtkWidget *pNewWindow = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_move(GTK_WINDOW(pNewWindow), 0, 0);
gtk_widget_show_all(pNewWindow);
while (gtk_events_pending())
gtk_main_iteration();
gtk_widget_set_size_request(pNewWindow, width, height);
gtk_window_set_decorated(GTK_WINDOW(pNewWindow), FALSE);
// gtk_window_set_position(GTK_WINDOW(pNewWindow), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_resizable(GTK_WINDOW(pNewWindow), FALSE);
// gtk_window_set_gravity(GTK_WINDOW(pNewWindow), GDK_GRAVITY_CENTER);
gtk_window_move(GTK_WINDOW(pNewWindow), 0, 0);
while (gtk_events_pending())
gtk_main_iteration();
return pNewWindow;
}

Unity3D ScrollView/ScrollBar from bottom to top

I'm trying to create a terminal emulator in Unity. I'm able to enter text and have it displayed as output above, and the output will generate a scrollbar when enough text is entered via a ScrollView.
However I can't figure out how to make the scrollbar jump to the bottom when a user enters text.
This is the method used to draw the GUI Window.
// relevant instance variables
private Rect _windowPosition = new Rect();
List<string> output = new List<string>();
string user_input = "";
Vector2 scroll_pos = new Vector2(1,1);
...
...
...
private void onWindow(int windowID){
GUILayout.BeginVertical();
// Output is placed here. Is Scrollable
scroll_pos = GUILayout.BeginScrollView( scroll_pos );
GUILayout.Label( String.Join("\n", output.ToArray()) );
GUILayout.EndScrollView();
// Output ends here. Next piece is user input
user_input = GUILayout.TextField(user_input);
if (Event.current.Equals(Event.KeyboardEvent("return"))) {
output.Add(user_input);
user_input = ""; //clears the TextField
scroll_pos.x = 1;
scroll_pos.y = 1;
}
GUILayout.EndVertical();
GUI.DragWindow();
}
From my searching, I'd seen it said that I should just change the scroll_pos variable, since that's used to control/read the scrollbar's position. The scrollbar's value is normalized between 0 - 1.
I've tried forcing the scroll_pos values to be both, 0 and 1, but it has no impact. Beyond this I'm not sure how to approach the problem.
Try to change
scroll_pos.x = 1;
scroll_pos.y = 1;
to
scroll_pos.y += 9999;
if you want to force scroll on horizontal do it with X too but usually consoles doesn't generates horizontal scroll, they force line breaks based on how many columns you configure.

Auto scroll a gtkscrolledwindow

I have a form interface with a large number of horizontal drop down and text boxes that are inside a GTKscrolledWindow. The form has to be aligned horizontally because there are an unlimited number of forms in the window (think tabel of forms).
Is it (possible/how do I) auto-scroll the GTKScrolledWindow to the right when the operator tabs to the next form control which is off to the right of the screen.?
Related question would be how do I detect if the focused element (button etc) is visible in it's parent scrolledwindow.
Thanks.
I hope you don't mind I am using GTK+ C API in the description, the sollution could be converted to the PyGTK easily and the principles remains the same.
Starting with the second question - if you know which widget to test, you can detect its visibility by calling gtk_widget_translate_coordinates(child, parent, 0, 0, &x, &y) to get the position of the child relative to the parent. By gtk_widget_get_allocation() you get the size of parent and child and you simply test if whole child rectangle is in the scrolled window.
gboolean is_visible_in (GtkWidget *child, GtkWidget *scrolled)
{
gint x, y;
GtkAllocation child_alloc, scroll_alloc;
gtk_widget_translate_coordinates (child, scrolled, 0, 0, &x, &y);
gtk_widget_get_allocation(child, &child_alloc);
gtk_widget_get_allocation(scrolled, &scroll_alloc);
return (x >= 0 && y >= 0)
&& x + child_alloc.width <= scroll_alloc.width
&& y + child_alloc.height <= scroll_alloc.height;
}
You can obtain the curently focused widget in window by gtk_window_get_focus () or you can detect it when focus is changed.
In the autoscroll problem you can handle "focus" signal connected to the widget which can be focussed or the "set-focus-child" event connected to the container containing the widgets. In the signal handler you should check, if the focused widget is visible. If not, determinate its position and scroll properly.
To do so you have to detect the position of the widget inside the whole scrolled area. If you are using some container which does not support scrolling (such GtkHBox) iside GtkScrolledWindow (adapted by viewport), you can get the coordinates of the focused widget relative to the container by gtk_widget_translate_coordinates() again - now using the container instead of scrolled window. The value of the adjustment, if using GtkViewport, the adjustment value correspond to the position in pixels in the scrolled area, so setting adjustment value to x relative coordinate will do scrolling. So the important part of the handler could be
GtkWidget *scrolled = /* The scrolled window */
GtkWidget *container = /* The container in the scrolled window */
GtkWidget *focused = /* The focused widget */
GtkAdjustment *hadj = gtk_scrolled_window_get_hadjustment(
GTK_SCROLLED_WINDOW(scrolled));
gint x, y;
gtk_widget_translate_coordinates (focused, container, 0, 0, &x, &y);
gtk_adjustment_set_value(hadj, min(x, maximal adjustment value allowed);
The maximal adjustment value allowed is adjustment.upper - adjustment.page_size. The focused widget is passed as signal handler argument for both signals, in the case of "set-focus-child" signal you get also the container as argument.
Here's what I did, based on Michy's answer.
To make a scrolled window auto-scroll, run in the constructor:
FocusScroll(scrolledwindow).
class FocusScroll(object):
"""
Get a gtk.ScrolledWindow which contains a gtk.Viewport.
Attach event handlers which will scroll it to show the focused widget.
"""
def __init__(self, scrolledwindow):
self.scrolledwindow = scrolledwindow
self.viewport = scrolledwindow.get_child()
assert isinstance(self.viewport, gtk.Viewport)
self.main_widget = self.viewport.get_child()
self.vadj = scrolledwindow.get_vadjustment()
self.window = self.get_window(scrolledwindow)
self.viewport.connect('set-focus-child', self.on_viewport_set_focus_child)
def get_window(self, widget):
if isinstance(widget, gtk.Window):
return widget
else:
return self.get_window(widget.get_parent())
def is_child(self, widget, container):
"""
Go recursively over all children of container, to check if widget is
a child of it.
"""
for child in container.get_children():
if child is widget:
return True
elif isinstance(child, gtk.Container):
if self.is_child(widget, child):
return True
else:
return False
def on_viewport_set_focus_child(self, _viewport, _child):
idle_add(self.scroll_slide_viewport)
def scroll_slide_viewport(self):
"""Scroll the viewport if needed to see the current focused widget"""
widget = self.window.get_focus()
if not self.is_child(widget, self.main_widget):
return
_wleft, wtop = widget.translate_coordinates(self.main_widget, 0, 0)
wbottom = wtop + widget.get_allocation().height
top = self.vadj.value
bottom = top + self.vadj.page_size
if wtop < top:
self.vadj.value = wtop
elif wbottom > bottom:
self.vadj.value = wbottom - self.vadj.page_size
First, the first.
How do you detect the focus ? You connect to GtkWidget::focus signal.
And in that callback you can scroll the window to whereever you like, how to do that, you need to get the GtkAdjustment of GtkScrolledWindow and move it accordinly to show what you want.