Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align Buttons and Textbox? #934

Open
skl131313 opened this issue Dec 9, 2016 · 11 comments
Open

Align Buttons and Textbox? #934

skl131313 opened this issue Dec 9, 2016 · 11 comments
Labels

Comments

@skl131313
Copy link

skl131313 commented Dec 9, 2016

I'm trying to get 3 buttons and a textbox on the same line along with a label. I want the text on the end to be aligned with everything else.

ImGui::Button("first"); ImGui::SameLine();
ImGui::Button("second"); ImGui::SameLine();
ImGui::Button("third"); ImGui::SameLine();
ImGui::InputText("##value", ... , ImGuiInputTextFlags_ReadOnly); ImGui::SameLine();
ImGui::TextUnformatted("name");'

// How it ends up formatted:
// [contents0              ] [ label ]
// [b1] [b2] [b3] [inputText    ] [ label ]
// [contents1              ] [ label ]
@ocornut
Copy link
Owner

ocornut commented Dec 9, 2016

Use PushItemWidth(n); with n being a negative number.

@skl131313
Copy link
Author

skl131313 commented Dec 9, 2016

How would I calculate the width then? I tried
PushItemWidth(-(GetWindowContentRegionWidth() - CalcItemWidth()))
but that doesn't seem to take indention into account.

@ocornut
Copy link
Owner

ocornut commented Dec 9, 2016

You don't, -n is the distance you want to be available for labels.

@skl131313
Copy link
Author

I want that distance to be the default, and i only want to set it for this one item. I don't want to change the width for all other items.

PushItemWidth(-(GetWindowContentRegionWidth() - CalcItemWidth()))

Does that except for when indention is used, such as in a tree node.

@ocornut
Copy link
Owner

ocornut commented Dec 9, 2016

Hmm it should be something like that but I'll look in details later. I agree it is an issue that this form of alignment isn't more readily obvious.

@colesnicov
Copy link

Hi sprinkle131313,

You solved it?I want to have an alignment button to the right so I tried:

I gained some numbers

int i = ImGui::GetCurrentWindow()->SizeContents.x;

And trying to offset follows

ImGui::Spacing ();
ImGui::SameLine(i - 60.0f);

or this way
ImGui::Indent(i - 60.0f);
and draw:
ImGui::Button("Cancel", ImVec2(60, 30));
Neither of them does not work correctly.

@skl131313
Copy link
Author

I never got it working completely. For your code though I think it's a bit different of a scenario.

Maybe this will help? #196

@colesnicov
Copy link

colesnicov commented Jan 9, 2017

yep, I saw it.

English language not learned much, I look at the text and are looking for familiar words :-D. I currently use this:

ImVec2 windowSize = ImGui::GetIO().DisplaySize - ImVec2(50, 60); // My ImGui window as fullscreen - padding (x=50, y=60)
ImVec2 buttonSize(60, 30); // My button size
ImGui::SetCursorPos(windowSize - ImVec2(10, 10) - buttonSize); // Move cursor on needed positions
ImGui::Button("Save", buttonSize))e - ImVec2(10, 10) - buttonSize); // Draw button

but sometimes it does not work properly. Specifically, I'm the one case that still has to remodel, Align button to the right but to me and to each frame in increasing the width and push the more to the right. It looks like a slide animations to hide the buttons: D Total funny ...

Ala google translate..

@JaminGrey
Copy link

JaminGrey commented Oct 29, 2017

(I wasn't sure what existing Issue to put this in, or whether I should start a new one about right-alignment)

I have multiple widgets on a line to the left, but I want to switch to a right-alignment on the same line, and have multiple widgets aligned right.

Here is how I currently do it:

const float ItemSpacing = ImGui::GetStyle().ItemSpacing.x;

static float HostButtonWidth = 100.0f; //The 100.0f is just a guess size for the first frame.
float pos = HostButtonWidth + ItemSpacing;
ImGui::SameLine(ImGui::GetWindowWidth() - pos);
if(ImGui::SmallButton("Become host"))
{ ... }
HostButtonWidth = ImGui::GetItemRectSize().x; //Get the actual width for next frame.

static float ClientButtonWidth = 100.0f;
pos += ClientButtonWidth + ItemSpacing;
ImGui::SameLine(ImGui::GetWindowWidth() - pos);
if(ImGui::SmallButton("Connect as client"))
{ ... }
ClientButtonWidth = ImGui::GetItemRectSize().x; //Get the actual width for next frame.

static float LocalButtonWidth = 100.0f;
pos += LocalButtonWidth + ItemSpacing;
ImGui::SameLine(ImGui::GetWindowWidth() - pos);
if(ImGui::SmallButton("Play local"))
{ ... }
LocalButtonWidth = ImGui::GetItemRectSize().x; //Get the actual width for next frame.

Result:
imgui right-aligned

This works fine. However, I'd like an API interface like this:

ImGui::Button("..blah..."); //...blah... existing left-aligned widgets.
ImGui::SameLine();
ImGui::Button("..blah 2..."); //Cursor automatically increases by the width of the previous widget.
ImGui::SameLine();

//Reset the cursor to "ImGui::GetWindowWidth()" (or to 0, if ImGui_Alignment_Left).
//Set internal alignment flag.
ImGui::SetAlignment(ImGui_Alignment_Right);

ImGui::Button("..I'm aligned right..."); //Cursor automatically subtracks the width of the previous widget.
ImGui::SameLine();
ImGui::Button("..I'm also aligned right...");

Each call to ImGui::SetAlignment() entirely resets the cursor position (to 0 or the window width, depending on the alignment enum passed in). So doing SetAlignment(right), drawing widgets, SetAlignment(left), drawing widgets, and then SetAlignment(right) does not preserve the previous cursor positions, and will of-course draw over the widgets you originally drew.

Edit: If in a column or child frame, it should right-align to the side of that column/frame. So I guess always just right-align to the end of the current column width, because even child-frames have single-columns unless specified otherwise, I think?

It may also be good to think of a similar syntax for vertical alignment - e.g. drawing buttons pinned to the bottom of the window. How that should or shouldn't interact with automatic window resizing, I haven't a clue (maybe each bottom-aligned new line should add to the total height, just as each top-aligned already does. Swapping back and force between vertical alignments should probably - for simplicity of coding - also just reset the (vertical) cursor position entirely).

Entirely unrelated, but it'd also be nice to have:

PushSameLine();
//...multiple widgets...
PopSameLine();

...where we don't have to call SameLine() between each widget.
Requiring SameLine() should still be the default.

@ocornut ocornut added the layout label Oct 29, 2017
@ocornut
Copy link
Owner

ocornut commented Oct 29, 2017

@JaminGrey Thanks for that post. This is something that I've been discussing with someone recently. I think it is worthy of a new thread but fine here as the thread is open. As part of improving layout features support for basic filling from one of 4-way will be desirable.

One thing to consider, is that most of the widgets or usage patterns don't take into consideration that there is a limit, so what do we do when you reach it (e.g. submit too many buttons). We can just a hard clipping line but we need to make sure the implementation doesn't make us end up with too many draw calls.

We could probably do the ground work to expose this internally with at minimum backuping the position on each side, that wouldn't be too hard and probably useful as a start.

Entirely unrelated, but it'd also be nice to have:
PushSameLine();
//...multiple widgets...
PopSameLine();

This is #97 (oldest open topic?). There is something internally where you can use window->DC.LayoutType = ImGuiLayoutType_Horizontal but it isn't finished or exposed, you can create yourself a helper to handle that stack, or a C++ helper that backups LayoutType, changes it, and restore on destruction.

I would like to introduce some sort of flow layout feature when layout can automatically go to the next line. It's not a very difficult feature per se but it will incur change to the code of every widget. Maybe will do this refactor before the end of year (I actually attempted it doing it four weeks ago, for this and for #395, and run into variety of problems and then I realized it wasn't a half-day refactor, more like a three-days one to do this right).

@moebiussurfing
Copy link

moebiussurfing commented Jan 21, 2023

Any news on that topic?

Looking for a layout helper to right-align widgets.
Or to exclude ImGui::NextLine sometimes depending on window width.
(to avoid populate non visible widgets out of the visible right window border, and put them on the next line.)

A found some workaround snippets but nothing serious yet...
Also some branches/forks like on here: #846

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants