How can I switch between two menu bars occupying the same space below the window title in GTK3? - gtk3

I like to switch menu bars depending on a button or internal state (COM port used). How can I do that in GTK3+ (preferably using Glade and GtkBuilder)? GtkOverlay does not seem to be the correct approach.

Put both menubars in a gtk(v)box and just declare one of the menubars as invisible in Glade (Leave the one you want by default visible). Then you can later switch menubars by hiding/showing them.
Mind, if you are on Ubuntu, you might run into problems. Ubuntu's Unity moves the menu bar to the top of the workspace, and it might not be happy with two menu bars just existing. In a program I made a couple of years ago Ubuntu refused to show the second menu (but I wasn't hiding either of them, so you might be in luck).

Thanks jcoppens for your answer, but I am not sure how the solution would look over all with one of the positions in the vertical box invisible but still occupying space / the height of one menu bar. Wouldn't that create a gap between either the title and the menu bar (first menu bar visible) or the menu bar and the container below (second menu bar visible)?
I solved it by (before I saw your answer):
Using Glade, create a new file and put the two menu bars in there.
In the Glade file for the main window, create a vertical box with one
item right below the title. (In my case, my main frame contains a
vertical box with three items, the first position is kept empty and
will contain one of the two menu bars, the second one contains all
other items inside another container, and the third item contains a
status bar.)
In the C module using GtkBuilder, I switch the menu bars as shown
below:
/**
* This function adds or replaces the menu bar.
* #param id id string for menu bar
*/
void amci_tester_set_menubar(const gchar *id) {
GtkWidget *menu_bar = GTK_WIDGET(gtk_builder_get_object(builder, id));
GtkBox *box_menu = GTK_BOX(gtk_builder_get_object(builder, "boxMainMenu"));
GList *children = gtk_container_get_children(GTK_CONTAINER(box_menu));
if (children != NULL)
gtk_container_remove(GTK_CONTAINER(box_menu), (GtkWidget *) g_list_first(children)->data);
gtk_box_pack_start(box_menu, menu_bar, false, false, 0);
// Although the visible property is shown as being set in the Glade GUI, in
// the Glade file it is not set.
gtk_widget_set_visible(menu_bar, true);
g_list_free(children);
}
In the beginning of main, I put the usual GtkBuilder stuff, instantiating a GtkBuilder object and then adding the default / first to be shown menu bar object:
// Init GTK+.
gtk_init(&argc, &argv);
// Create new GtkBuilder object from file.
builder = gtk_builder_new_from_file(glade_filename_app);
if (builder == NULL) {
g_warning("Could not create builder from %s", glade_filename_app);
return 1;
}
// Add menu bar for PC menu bar (default) from file.
if (!gtk_builder_add_from_file(builder, glade_filename_menu_pc, &error)) {
g_warning("%s", error->message);
g_free(error);
return 1;
}

Related

e4 RCP: programmatically open part in new window

I would like to programmatically open an MPart in a new MWindow.
Similar to as if I would create the part in a partstack somewhere in the existing window and then manually drag it away with the mouse.
So, one way would be to create a non-rendered window which contains this part. And once it should be shown, we can set it to being rendered. But: once we close this window, we cannot bring it back?!
This approach worked for me:
Define an empty window in the e4xmi which is set to not be rendered
Once we want to display the part, we create it (if it is not open already) and add it to the window
MUIElement window = modelService.find(myWindowId, app);
MPart part = (MPart) modelService.find(myPartId, application);
if (part == null) {
part = MBasicFactory.INSTANCE.createPart();
part.setLabel(ProcedureFlowChartPart.PART_TITLE);
part.setContributionURI("bundleclass://MyPartPath");
part.setElementId(myPartId);
((MWindow) window).getChildren().add(part);
}
partService.showPart(part, PartState.ACTIVATE);
window.setToBeRendered(true);
modelService.bringToTop(window);

MPart is not user after switch perspective

I have an issue related to switching perspectives in E4. The two perspectives shares the same MPart. After switching to a new perspective the new MPart will be used. After swithing back to the original perspective the second MPart will still be used instead of the first one.
In the image you can find the application structure and both of the Perspectives has Outline screen on it.
When opening perspective one, the Outline works for that perspective. Then if we switch to perspective two (that has different other screen) the second Outline will be activated and works correct. When switching back to the first perspective the second Outline will be still active and the first Outline will not respond to any requests.
After switching to perspective I active all the MPart back with:
List<MPart> part = service.findElements(perspective, null, MPart.class, null);
List<MPartStack> mainPartStack = service.findElements(perspective, "partstack.shared", MPartStack.class, null);
if (!mainPartStack.isEmpty()) {
for (int i = part.size() - 1; i >= 0; i--) {
List<MPart> children = service.findElements(mainPartStack.get(0), part.get(i).getElementId(), MPart.class,
null);
if (!children.contains(part.get(i))) {
this.partService.activate(part.get(i));
}
}
}
How can I activate the first Outline back so that it will respond to new request from the first perspective?
Created a shared Outline part and use a placeholder to reuse the Outline. With this solution I changed the perspective switch implementation. So that if a user go back to the first perspective that the data of the outline is the same when he was switching to the second.

How to Change the cursor in JavaFX Accordion title bar

I'm using custom cursors and it need to be differ in some components in my screen.
When I set the cursor for Accordion, it doesn't effects title headers but effects the body of each TitledPanes. I even tried to set the cursor for each TitledPane but it doesn't effect the title header. I'm using following way to change the cursor.
ImageCursor cursor_title = new ImageCursor(cursorImg_title,cursorImg_title.getWidth() / 2,cursorImg_title.getHeight() / 2);
accordionBody.setCursor(cursor_title);
Is there a way to change the cursor in title bar of a JavaFX Accordian?
More....
I have changed the padding of title bars using css as follows. Hope it doesn't have any relation to the problem.
.titled-pane > .title {
-fx-padding: 30;
}
A TitledPane is divided into two parts :
Title
Content
When you are setting the Cursor on the Accordion, it delegates it to the content of each TitledPane, but leaves the Title. This is by design.
To force your application to change the cursor on the title as well, we need to set it on each of these nodes. We can fetch all the nodes by using the lookupAll() on the accordion and passing the styleclass they use i.e. .title. Make sure you use this after the scene graph is visible.
accordion.lookupAll(".title").forEach(node -> node.setCursor(Cursor.CLOSED_HAND));
You can use your custom cursor in place of CLOSED_HAND.

Eclipse ui: retrieving the first visible line of an editor

In the Eclipse UI, I'd like to set the visible area in an editor. In other words, if the number of lines of my file is larger than the number of lines my editor can show then I want to specify the first shown line. My first approach was to calculate the first visible line via the selection value of its vertical scroll bar. The following link points to my initial question. Its answer explains how to set the first visible line in an editor.
eclipse ui: setting scrollbar but editor does not follow
The problem now is that my initial way of retrieving the first visible line in an editor fails in some cases: Although I verify that the active page is indeed an editor, the focus might be assigned to another page. In such a case, the following code yields the ScrollBar of a different page:
public static void update(final IWorkbenchWindow w)
final Scrollable scrollable =
(Scrollable) w.getWorkbench().getDisplay().getFocusControl();
final ScrollBar vScrollBar = scrollable.getVerticalBar();
So, my question: If editor is the reference of an active editor (ITextEditor and IReusableEditor), how to I get its first visible line?
If you can access the editor ITextViewer or its extension ISourceViewer (usually implemented by the SourceViewer or TextViewer class) you can call the ITextViewer.getTopIndex() method to get the top line index.
If your editor is derived from AbstractTextEditor (or one of its subclasses such as TextEditor) there is a protected method getSourceViewer() that returns this. You may have to add a public method if you want to access this from outside of the editor.

gtkmm button not maintaining size and location

I have created two gtkmm button and added to HBox object. I called pack_end, and maintained the size as 21,20. But, the sizes are not maintained. Here is the code i have written and the window that i got while running the program.
Note: MYWindow is subclass of Gtk::Window
void MYWindow::customizeTitleBar()
{
//create a vertical box
Gtk::VBox *vBox = new Gtk::VBox(FALSE,0);
//create a horizontal box
Gtk::HBox *hBox = new Gtk::HBox(TRUE,0);
hBox->set_border_width(5);
//create title bar image
Gtk::Image *titleBarImage = new Gtk::Image("src/WindowTitleBar.png");
titleBarImage->set_alignment(Gtk::ALIGN_LEFT);
// hBox->pack_start(*titleBarImage,Gtk::PACK_EXPAND_WIDGET,0);
//create cloze button for window
mButtonClose = new Gtk::Button;
(*mButtonClose).set_size_request(21,20);
Gtk::Image *mImage = new Gtk::Image("src/Maximize.jpeg");
(*mButtonClose).add(*mImage);
(*mButtonClose).set_image_position(Gtk::POS_TOP);
// connecting close window function when cliked on close button
//(*mButtonClose).signal_clicked().connect( sigc::mem_fun(this, &MYWindow::closeWindow));
hBox->pack_end(*mButtonClose,Gtk::PACK_EXPAND_WIDGET,0);
Gtk::Button * mBtton = new Gtk::Button;
mBtton->set_size_request(21,20);
Gtk::Image *img = new Gtk::Image("src/Maximize.jpeg");
mBtton->add(*img);
mBtton->set_image_position(Gtk::POS_TOP);
hBox->pack_end(*mBtton,Gtk::PACK_EXPAND_WIDGET,0);
vBox->add(*hBox);
//drawing area box
Gtk::HBox *hBoxDrawingArea = new Gtk::HBox;
Gtk::DrawingArea *mDrawingArea = new Gtk::DrawingArea;
hBoxDrawingArea->pack_start(*mDrawingArea,Gtk::PACK_EXPAND_WIDGET,0);
vBox->add(*hBoxDrawingArea);
//status bar hBox
Gtk::HBox *hBoxStatusBar = new Gtk::HBox;
vBox->add(*hBoxStatusBar);
this->add(*vBox);
this->show_all();
}
I am not yet a gtk expert (but I'm learning), here's one thing you can try, which is what I've been doing.
Make a little standalone project using glade. Glade makes it really easy to screw around with all the packing settings so you can immediately see the effects of your changes.
I think in the case of resizing the window, you'll have to save the glade file and run your program (using gtkbuilder to render the glade file) and manually resize the window to see the effect, but once you make the standalone project, you can use it for other gtk testing.
And if you're like me, you'll get swayed by the wonderfulness that is glade and build your whole system that way.
But basically, it sounds like a packing issue, because I've got buttons that don't resize all over the place.
As for not moving, I'm not sure you can do that, but again I'm not an expert. I think you should be able to pin the size of some if not all of the hbox pieces so that the button inside them will not move, but I'm not sure what happens if you don't have any hbox parts that can't be variably sized to take up the slack when you grow the window.
Again, sounds like something fun to try in glade. :-)
I think you pack to FALSE , Maybe this is the problem :
Gtk::HBox *hBox = new Gtk::HBox(TRUE,0)
I use python gtk with something like this:
box1.pack_start(box2,False)