How to make StackSwitcher tabs closeable Gtk/Vala - gtk

I am trying to make a Stack and StackSwitcher whose pages associated tabs can be added and deleted dynamically. To delete the associated widget in the stack and the tab in the StackSwitcher, I want to have a small delete button in the tab. I have found an example similar to this in the gtk3-widget-factory, screenshot shown below.
However, this uses a Notebook and I would like to be able to use the Stack/StackSwitcher setup instead of a Notebook (I don't like how the Notebook creates a background to its pages). I can't figure out how to change the widget that is displayed in the StackSwitcher for each page in the Stack. My intuition is that I should just be able to replace the Label in the StackSwitcher with a Box that has been packed with a Label and Button that has a callback that goes and removes the page and the tab. But I am not able to do this with how I am currently creating the pages of the Stack, which is by calling stack.add_titled(). The StackSwitcher that has been assigned to that stack just automatically picks up the labels with no way of editing them that I have found.
Is there a way to do this for a Stack and StackSwitcher? If not, I would also appreciate some advice for doing it with a Notebook as I have not even been able to recreate what I saw in the widget factory (above). This is the code that I have attempting to recreate it:
void main (string[] args) {
Gtk.init (ref args);
var window = new Window ();
window.title = "Example Program";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
Notebook note = new Notebook();
Box tabBox = new Box(Orientation.HORIZONTAL, 0);
Label tabLabel = new Label("Closable Tab");
Button closeButton = new Button.from_icon_name("window-close-symbolic", IconSize.BUTTON);
tabBox.pack_start(tabLabel, false, false, 0);
tabBox.pack_start(closeButton, false, false, 0);
Label displayLabel = new Label("this page should be closeable");
note.append_page(displayLabel, tabBox);
window.add(note);
window.show_all();
Gtk.main ();
}
which just creates an empty Notebook tab like this:
and I don't get any error messages about creating that tab failing so I don't know what to do. Any help is appreciated.

Related

Custom Perspective Switcher Toolbar: How can I dynamically update it?

I'm trying to implement a custom perspective switcher toolbar to replace eclipse's built-in one. I couldn't get the toolbar to display, and it was shown to me that due to a bug with the dynamic element in a menu contribution, I have to use a control element instead, as described in the workaround to the dynamic bug.
I have a toolbar displaying following that approach, but I cannot figure out how to update it dynamically. The workaround instruction is to call ContributionItem#fill(CoolBar, int) from my WorkbenchControlContributionItem's update method instead of doing the fill in the createControl method.
I don't know who is supposed to call update, but it never gets invoked no matter what I do. I have a perspective listener which knows when to update the toolbar, so from that listener's callback I call fill(CoolBar, int). But I wasn't sure how to get the CoolBar to pass to that method, so I created one on the current shell.
The end result of all this is that the toolbar displays the correct number of items initially, but when I need to add an item, it has no effect. I call fill(CoolBar, int) and it adds the new item to the toolbar, but everything I've tried to make the CoolBar and ToolBarupdate does not work. When I re-launch the app, the toolbar has the added item.
I'm sure I'm doing this wrong, but I can't figure out the right way. Here's an elided representation of my code (omitting methods, layout code, etc not related to the update problem).
public class PerspectiveSwitcherToolbar extends WorkbenchWindowControlContribution implements IPerspectiveListener {
...
#Override
protected Control createControl(Composite parent) {
this.parent = parent;
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.getWorkbenchWindow().addPerspectiveListener(this);
toolBarManager = (ToolBarManager)parent.getParent().getData();
fTopControl = new Composite(parent, SWT.BORDER);
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
return fTopControl;
}
#Override
public void fill(CoolBar coolbar, int index) {
IPerspectiveDescriptor[] openPerspectives = page.getOpenPerspectives();
String activePerspective = getPerspectiveId();
ToolBar toolbar = new ToolBar(fTopControl, SWT.NONE);
for(IPerspectiveDescriptor descriptor : openPerspectives) {
ToolItem item = new ToolItem(toolbar, SWT.RADIO);
//overkill here, trying to find some way to upate the toolbar
toolbar.update();
parent.update();
parent.layout(true);
parent.getParent().update();
parent.getParent().layout(true);
coolbar.layout(true);
}
//PerspectiveListener callback
#Override
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
if (page.getWorkbenchWindow() instanceof WorkbenchWindow){
//this non-API call doesn't help either
((WorkbenchWindow) page.getWorkbenchWindow()).updateActionBars();
}
}
...
}

How to open a filedialog within an Eclipse Wizard

I'm writing an Eclipseplugin, which has to create a new project. This works so far, but i need to copy an external file into the projectfolder. I intend to have a 'Browse' button on one of my WizardPages, which opens a filedialog, where the user can browse to the file and after closing the dialog i can use the path to this file for various actions. My problem is that the dialog window never opens. Right now i'm trying it that way (snippet from my wizardpage):
public void createControl(Composite composite) {
this.container = new Composite(composite, SWT.NONE);
GridLayout layout = new GridLayout();
this.container.setLayout(layout);
layout.numColumns = 2;
Button browseButton = new Button(this.container, SWT.PUSH);
browseButton.setText("Browse");
browseButton.addSelectionListener(new SelectionListener() {
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
FileDialog fileDialog = new FileDialog(DataPage.this.container.getShell(), SWT.OPEN);
fileDialog.setText("JZOS created File");
String path = fileDialog.open();
DataPage.this.setJzosCreatedName(path);
}
});
I tried several implementations, that i have seen in examples and tutorials but nothing did work. I'm assuming a problem with the Shell that i give to the filedialog. I tried to open a new Shell within the widgetDefaultSelected function but it didn't work either. Any Suggestions?
You should be using the widgetSelected method of SelectionListener not widgetDefaultSelected

Opening 2 Views in a new window

When the user peforms a certain action from a view i want to open a new window containing extra information. Currently i can open a view in a new window but i can not add a second view below it in the same window.
EModelService service = (EModelService) getSite().getService(EModelService.class);
IViewPart topView = getSite().getPage().showView(topid, "secondid", IWorkbenchPage.VIEW_VISIBLE);
MPart topPart = (MPart) topView .getSite().getService(MPart.class);
IViewPart botView = getSite().getPage().showView(botid, "secondid", IWorkbenchPage.VIEW_VISIBLE);
MPart botPart = (MPart) botView.getSite().getService(MPart.class);
service.detach(topPart, 100, 100, 300, 300);
service.insert(botPart, topPart, EModelService.BELOW, 1f);
the top view gets detached and put in a new (trimmed)window but botpart does not get inserted below it into the window.
can anyone tell me why it does not get inserted? Or maybe does someone have some more information about how EModelSerice should be used.
thanks in advance

SmartGwt - Removing one tab clears the canvas

I've built a GUI with a SmartGWT TabSet with Tabs that can be dynamically added and removed.
The Tabs share the same canvas which is moved from Tab to Tab at each tab selection like this:
myTabSet.addTabSelectedHandler(new TabSelectedHandler() {
public void onTabSelected(TabSelectedEvent event) {
[...]
myTabs[myTabSet.getSelectedTabNumber()].setPane(myCanvas);
// Then I fill the contained widgets with the tab-specific data
}
}
This works, but when I try to remove a Tab with
myTabSet.removeTab(iToBeDeletedTab);
The tab is removed but the remaining tabs have a blank pane, I can get the content back only by reloading the page. I found that I have to prevent pane destruction with calls to :
myTabSet.setDestroyPanes(false);
and
myTabSet.updateTab(iToBeDeletedTab, null);
//called right before
myTabSet.removeTab(iToBeDeletedTab);
I understand that the canvas/pane is still destroyed, but I cannot figure out how to prevent this.
Has anyone any hint?
Thank you!
Have you tried to call the redraw() method after removing a tab? This usually helps me when loading/reloading data with smartGWT widgets.
Your calls are correct, but now what you've got is the pane completely unnassociated from the TabSet and not drawn (check the Watch Tab in the Developer Console and you'll see this). Now, call updateTab(someOtherTab, pane) to connect the pane to one of the other tabs where it should be showing.
Ok, I've made some test and got the same as you but had some success with the following code:
1°) in the Javadoc I found:
***public void setPane(Canvas pane)
Specifies the pane associated with this tab. You can change the pane associated with a given tab after the TabSet has been created by calling TabSet.updateTab(int, com.smartgwt.client.widgets.Canvas)***
I tried without setting to null the pane of tab1 , it didn't work.
I think it could be arranged in better way but anyway the point is to use the updatePadmethod
public static void testTabDelete(){
final Canvas theCanvas = new Canvas();
final TabSet theTabs = new TabSet();
theTabs.setWidth("80%");
theTabs.setHeight("80%");
final Tab tab1 = new Tab("Tab1");
final Tab tab2 = new Tab("Tab2");
final Tab tab3 = new Tab("Tab3");
IButton btn1 = new IButton("Btn1");
btn1.setLeft(10);
btn1.setTop(100);
btn1.setWidth(80);
theCanvas.addChild(btn1);
IButton btn2 = new IButton("Delete");
btn2.setLeft(100);
btn2.setTop(100);
btn2.setWidth(80);
btn2.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
#Override
public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
theTabs.updateTab(0, null);
theTabs.updateTab(1, theCanvas);
theTabs.selectTab(tab2);
theTabs.removeTab(tab1);
}
});
theCanvas.addChild(btn2);
theTabs.addTab(tab1);
theTabs.addTab(tab2);
theTabs.addTab(tab3);
tab1.setPane(theCanvas);
RootPanel.get("container").add(theTabs);
}

Whats the best way to programatically open a pane inside Dijit AccordionContainer

I am trying open & close accordion panes programatically. Here is the simplified version of my code. Even though I set the first pane's selected to false and and second pane's selected to true, only the first pane opens when it loads on the browser (FF3).
var accordionContainer = new dijit.layout.AccordionContainer().placeAt("test");
var accordPane = new dijit.layout.ContentPane({"title": "test", "content":"hello"});
var accordPane2 = new dijit.layout.ContentPane({"title": "test1", "content":"hello1"});
accordionContainer.addChild(accordPane);
accordionContainer.addChild(accordPane2, 1);
accordPane.startup();
accordPane2.startup();
//accordionContainer.selectChild(accordPane2);
accordionContainer.startup();
accordPane.selected = false;
accordPane2.selected = true;
You can do it like this:
accordionContainer.selectChild( accordPane2 );
Assuming you are using dojo 1.3.
dijit.layout.AccordionContainer is a subclass of dijit.layout.StackContainer, which has selectChild defined.
I set up a demo page where you can see this code in action
If you were calling selectChild before startup, that could cause the error you were seeing since the widget wasn't in a 'complete' state. (Sorry, missed the commneted out code before I posted original answer)