I have got ditched in a problem with Menu Contribution and PersistedState. I had no problem before removing the -clearPersistedState flag from the VM args.
Now, the app has a weird behaviour, the menu contribution starts to pile up a menu entry every time the code is executed.
Here it's the guilty snippet enclosed in a Processor:
MDirectMenuItem menuItem = MMenuFactory.INSTANCE.createDirectMenuItem();
menuItem.setLabel("Another Exit");
menuItem.setContributionURI("bundleclass://"
+ "com.telespazio.optsat.wizard/"
+ ExitHandlerWithCheck.class.getName());
if (!menu.getChildren().contains(menuItem))
menu.getChildren().add(menuItem);
The menu items you add to the application model will be persisted, so you need to check if they already exist in the menu. The contains check you currently have does not do this.
You need to check for a match of the label (or the contribution URI, or the id), something like:
List<MMenuElement> children = menu.getChildren();
boolean gotExisting = false;
for (MMenuElement child : children)
{
if ("Another Exit".equals(child.getLabel())
{
gotExisting = true;
break;
}
}
if (!gotExisting)
{
... add to menu
}
Related
Hi I'm working with composite pattern. I'm going to use this example of Head First Design Pattern to explain https://github.com/bethrobson/Head-First-Design-Patterns/tree/master/src/headfirst/designpatterns/composite/menuiterator
Imagine that every menu and submenu have an Id to indentify, it is 10 length.
Something like this
0100000000 menu_1
0101000000 menu_1's subMenu_1
0102000000 menu_1's subMenu_2
0102010000 subMenu_2's subMenu_3
0200000000 menu_2
And what I have at random is the menu item, but it has an ID, which is a Menu ID to which it belongs. For example
0101000000 menuItem_1
0200000000 menuItem_2
So MenuItem 1 belongs to Menu 1's SubMenu 1 and MenuItem 2 belongs to Menu 2.
It would be coded like this.
menu_1.add(subMenu_1);
subMenu_1.add(menuItem_1);
menu_2.add(menuItem_2);
Now how am I filling the menus?
What I'm doing because of I get only the MenuItems, is that I'm cutting the Id to determine where it belongs.
For example you can see that there two Menus, Menu 1 (0100000000) and Menu 2 (0200000000) so I have to cut the first 2 Strings.
I'm coding like this:
class AllMenus implements MenuComponent {
MenuComponent menu_1
MenuComponent subMenu_1
MenuComponent subMenu_2
MenuComponent subMenu_3
MenuComponent menu_2
#Override
add(MenuComponent menu) {
if(menu instanceof Menu) {
super.add(menu)
} else if(menu instanceof MenuItem) {
String subId = menuItem.getId().subString(0,2)
if(subId.equals("01")) {
if(menu_1 == null) {
menu_1 = new Menu();
add(menu_1);
}
subId = menuItem.getId().subString(0,4);
if(subId.equals("0101")) {
if(subMenu_1 == null) {
subMenu_1 = new Menu();
menu_1.add(subMenu_1);
}
subMenu_1.add(menuItem);
} else if(subId.equals("0102")) {
if(subMenu_2 == null) {
subMenu_2 = new Menu();
menu_1.add(subMenu_2);
}
subId = menuItem.getId().subString(0,6);
if(subId.equals("010201")) {
if(subMenu_3 == null) {
subMenu_3 = new Menu();
subMenu_2.add(subMenu_3);
}
subMenu_3.add(menuItem);
}
}
} else if(subId.equals("02") {
if(menu_2 == null) {
menu_2 = new Menu();
add(menu_2);
}
menu_2.add(menuItem);
}
}
}
}
This is for every MenuItem I get. So as you can see this code is to long just for four Menus,imagine thousands of menu, how can it get better?.
I have read that i should use polymorphism to something that repeat, but I don't know how in this case.
If I understand your question properly, I think there's too much assumption of the eventual structure in your code.
In general, number literals in your code should be treated with suspicion - e.g.
if(subId.equals("010201")
... because it looks like configuration, not code. Of course it's fine to put "configuration" in your code, and sometimes it's practical for that configuration to be program code rather than XML/CSV/JSON/etc. -- but even then, it's good to have a logical separation between a "config" class and a "code" class. For example your "config" class might just contain a method that returns arrays of strings:
public class MenuConfig() {
public String[][] configs() {
return new String[][] {
new String[] {"0100000000", "Main menu"},
new String[] {"0101000000", "Settings"},
new String[] {"0101010000", "Look and feel"},
new String[] {"0102000000", "My account"},
// etc.
}
}
}
You're looking to create a tree of submenus -- look for inspiration in code to manipulate trees (e.g. binary trees) -- see how simple the code is and how it doesn't make assumptions beyond the fact that each node has zero or more subnodes.
You're already using polymorphism -- your menus and submenus conform to a common type (I can't tell from your code whether they all have the same concrete type, but in principle I might expect you to have a variety of classes that implement MenuComponent.
Your code to process one menu just needs to parse the ID to work out where it's supposed to go, then find the place it needs to go, and insert it:
(I'm presenting the IDs with hyphens to make it easier to read)
// split "01-02-03-00-00" into [1,2,3] -- ignoring trailing zeros
List<Integer> path = parse(currentMenu.getId());
MenuComponent m = rootMenuComponent;
while(path.size() > 1) {
m = m.getSubMenu(path.remove(0));
}
m.add(path.remove(0), currentMenu());
This simple algorithm assumes that menus are added in the right order -- that is you must have handled 01-02-00-00-00 before 01-02-01-00-00, or you'll get a null pointer.
If you can't live with that constraint, you need to define what could happen, and decide how to deal with it.
Actually with your current scheme, sorting the keys alphabetically should be sufficient
If they're just going to come out-of-order, you could treat the to-do-list of menus to be added as a queue. If a particular item can't yet be added, put it to the back of the queue and retry after processing the rest.
If you want it not to be necessary to explicitly define intermediate menus, then when m.getSubMenu(subMenuNum) returns null (because you've implicitly "defined" it in the middle of a path) you'll need to create the missing menu at that point.
If you want it to be possible to define the same menu more than once (maybe both implicitly and explicitly) then you need MenuComponent.add() to handle that case, either by merging or overwriting, depending on your requirement.
Assembling a graph of nodes like this is what Spring dependency-injection does -- handling building the graph in order, when the dependencies are defined in arbitrary order. If your aim is study, keep building your own. If you just want build a composite of menus, consider using Spring (or some other DI framework).
I am using dhtmlxgrid but my first row doesn't get selected upon using onRowSelect but works fine upond using the event onRowDblClicked or I use keyboard navigation. But upon using keyboard nagivation and navigating to the first row, the navigation gets stuck and I cannot navigate from the first row using the keyboard but clicking on a different row works fine. Here's my code:
function onGraphPropGridRowSelect(id)
{
// push the previously selected graph's data to the JSON array object
if(lastSelectedGraphIndex != -1)
{
if(validateGraphProperties())
{
// Note: GraphType is uneditable, so just copy existing value
pushGraphPropertiesToJSONArr(lastSelectedGraphIndex,
graphPropertiesJson[lastSelectedGraphIndex].GraphType);
}else
{
definedGraphGrid.selectRow(definedGraphGrid.getRowIndex(lastSelectedGraphIndex));
return false;
}
}
// now populate the newly selected graph data to the UI elements
populateUIElementsForSelectedGraph(id);
// update the lastSelectedGraphIndex to the newly selected graph index
lastSelectedGraphIndex = id;
if (id==0){
definedGraphGrid.enableKeyboardSupport(true);
alert("first row selected");
}
}
Unfortunately it is not available to use the "0" as an ID of the row. Please, try to use another id.
I'm using gxt 2.0.3 in Java and I have created a SimpleComboBox which I then populate with 2 strings.
final SimpleComboBox<String> accessedComboBox = new SimpleComboBox<String>();
accessedComboBox.setTriggerAction(TriggerAction.ALL);
accessedComboBox.setEmptyText("Select a type");
accessedComboBox.add("Method 1");
accessedComboBox.add("Method 2");
I also have a listener attached to a different SimpleComboBox and depending on what is selected I need to either add or remove the value from the above accessedComboBox
if (typeComboBox.getSimpleValue() == "Type 1")
{
//Remove desktop app option
accessedComboBox.remove("Method 2");
}
else
{
if (accessedComboBox.??) { // <--- Check to see whether desktop app is an option
//if not then add it
accessedComboBox.add("Method 2");
}
}
I can't work out what function to use to check the see whether an option already exists in the SimpleComboBox. I have looked in this documentation but I've still had no luck.
Can anyone help?
Not sure if you got this yet. It's a little funky, but you can get the String values from the ListStore. Something like this:
for (SimpleComboValue<String> value : accessedComboBox.getStore().getModels()) {
if (!value.getValue().equals("Method 1")){
accessedComboBox.add("Method 1");
}
}
I have a treeView in my wizard application. Whenever i add or remove an object from my model , calling the update or refresh methods works as expected. What i want is , when i press a certain check button, two things may happen: If the new selection is false(unchecked) , i want to remove the treeView items , so they wont show in my UI, and when the new selection is true(checked) , i want to add the previously removed items (i have them stored in my application), so they can show up again. So i added this listener to my button :
oIsAuthorizableResourceButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
bIsResourceAuthorizable[intSelectedResourceIndex] = oIsAuthorizableResourceButton.getSelection();
//recursiveSetEnabled(grpPolicySetConfiguration,oIsAuthorizableResourceButton.getSelection());
if(!bIsResourceAuthorizable[intSelectedResourceIndex]){
System.out.println("Remove : " + oSelectedPolicySet.getHasResourceAccessPolicy().size());
oTreeViewer.remove(oSelectedPolicySet.getHasResourceAccessPolicy().toArray());
oTreeViewer.refresh(oSelectedPolicySet);
oTreeViewer.refresh();
}else{
System.out.println("Add : " + oSelectedPolicySet.getHasResourceAccessPolicy().size());
oTreeViewer.add(oSelectedPolicySet, oSelectedPolicySet.getHasResourceAccessPolicy().toArray());
oTreeViewer.refresh(oSelectedPolicySet);
oTreeViewer.refresh();
}
}
Well this code does absolutely nothing.Any help appreciated.
Implement a Viewer Filter, then add and remove it from your viewer: http://www.eclipse.org/articles/Article-TreeViewer/TreeViewerArticle.htm . What it filters, and whether it even cares about a specific property, is your choice.
I have created a drop down list using JAVA Swing. When I select "Keep track of status of RCM:", I want to create another drop down list next to the option selected. should I use mouseactionlistener instead? I trying to accomplish something like in this, when I click menu options, there is another list which I can select under menu options category. Example : http://smoothjazztampabay.com/wp-content/rockettheme/rt_metropolis_wp/menu-options/dropdownmenu.jpg
I tried using this code but couldn't.
if (state == ItemEvent.SELECTED)
{
ItemSelectable itemS = itemEvent.getItemSelectable();
String cmd = selectedString(itemS);
if ( cmd.equals("Keep track of status of RCM:"))
{
RCMCombo2.addItem(RCMCombo);
selectionPanel.add(RCMCombo2);
}
The full version of the code is shown as below:
String [] RCM2 = {"Keep track of status of RCM:", "Add and activate RCM", "Remove RCM",
"Display the usage statistics for RCM",
"Update capabilities of RCMs", "Show RCM used most frequently in the last n days",
"Display number of times the RCM was emptied in n hours"};
RCMCombo2 = new JComboBox(RCM2);
RCMCombo2.addItemListener(itemListener);
RCMCombo2.setEditable(false);
RCMCombo2.setBounds(10,10,10,30);
//"Updates capabilities of RCM"); Get the location of RCM");
selectionPanel.add(RCMCombo2);
ItemListener itemListener = new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int state = itemEvent.getStateChange();
//System.out.println((state == ItemEvent.SELECTED) ? "Selected" : "Deselected");
//System.out.println("Item: " + itemEvent.getItem());
if (state == ItemEvent.SELECTED)
{
ItemSelectable itemS = itemEvent.getItemSelectable();
String cmd = selectedString(itemS);
if ( cmd.equals("Keep track of status of RCM:"))
{
RCMCombo2.addItem(RCMCombo2);
selectionPanel.add(RCMCombo2);
}
Any help will be appreciated. Thank you.
It looks like you are on a completely wrong track. I think you are mixing the usage of ItemListener with the setup of the lists model.
Check out this guide to ComboBox - it should contain all the information you need.