浏览代码

Copied the new MenuBar component from Incubator to Trunk. Fixes #1852.

svn changeset:4955/svn branch:trunk
tags/6.7.0.beta1
Marko Grönroos 16 年前
父节点
当前提交
5babab8d3c

+ 58
- 0
WebContent/ITMILL/themes/default/styles.css 查看文件

@@ -602,6 +602,64 @@ input.i-modified,
.i-gridlayout-spacing .i-gridlayout-firstrow {
padding-top: 0;
}
/*Set the style for the menu bar itself */
.i-menubar table{
border-right: 2px solid #c6cbcc;
border-bottom: 2px solid #c6cbcc;
border-top: 1px solid #d0d4d5;
border-left: 1px solid #d0d4d5;
padding 3px;
}

/*Set the style for the main menu menu items */
.i-menubar .gwt-MenuItem {
cursor : hand;
cursor : pointer;
padding : 1px 10px;
margin : 1px 10px;
}

/*Set the style for the selected main menu menu item */
.i-menubar .gwt-MenuItem-selected {
background-color : #fff;
}


/*Set the style for the submenus */
.gwt-MenuBar {
font-size : 12px;
padding : 3px;
font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif;
color: #464f52;
border-right: 2px solid #c6cbcc;
border-bottom: 2px solid #c6cbcc;
border-top: 1px solid #d0d4d5;
border-left: 1px solid #d0d4d5;
}

/*Set style for the submenu menu items */
.gwt-MenuBar .gwt-MenuItem {
cursor : hand;
cursor : pointer;

//border : 1px solid #999;
//background-color : #eee;
padding : 2px 10px;
}

/*Set style for the selected submenu item */
.gwt-MenuBar .gwt-MenuItem-selected {
background-color : #fff;
}

.gwt-MenuItem p{
padding : 0;
margin : 0;
line-height : normal;
}

.i-Notification {
font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif;

+ 6
- 0
src/com/itmill/toolkit/terminal/gwt/client/DefaultWidgetSet.java 查看文件

@@ -25,6 +25,7 @@ import com.itmill.toolkit.terminal.gwt.client.ui.IHorizontalExpandLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.ILabel;
import com.itmill.toolkit.terminal.gwt.client.ui.ILink;
import com.itmill.toolkit.terminal.gwt.client.ui.IListSelect;
import com.itmill.toolkit.terminal.gwt.client.ui.IMenuBar;
import com.itmill.toolkit.terminal.gwt.client.ui.INativeSelect;
import com.itmill.toolkit.terminal.gwt.client.ui.IOptionGroup;
import com.itmill.toolkit.terminal.gwt.client.ui.IOrderedLayoutHorizontal;
@@ -190,6 +191,9 @@ public class DefaultWidgetSet implements WidgetSet {
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.IAccordion"
.equals(className)) {
return new IAccordion();
} else if ("com.itmill.toolkit.terminal.gwt.client.ui.IMenuBar"
.equals(className)) {
return new IMenuBar();
}

return new IUnknownComponent();
@@ -320,6 +324,8 @@ public class DefaultWidgetSet implements WidgetSet {
} else {
return "com.itmill.toolkit.terminal.gwt.client.ui.IExpandLayout";
}
} else if ("menubar".equals(tag)) {
return "com.itmill.toolkit.terminal.gwt.client.ui.IMenuBar";
}

return "com.itmill.toolkit.terminal.gwt.client.ui.IUnknownComponent";

+ 152
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/IMenuBar.java 查看文件

@@ -0,0 +1,152 @@
package com.itmill.toolkit.terminal.gwt.client.ui;

import java.util.Iterator;
import java.util.Stack;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;

public class IMenuBar extends MenuBar implements Paintable {

/** Set the CSS class name to allow styling. */
public static final String CLASSNAME = "i-menubar";

/** Component identifier in UIDL communications. */
protected String uidlId;

/** Reference to the server connection object. */
protected ApplicationConnection client;

/** A host reference for the Command objects */
protected final IMenuBar hostReference = this;

/**
* The constructor should first call super() to initialize the component and
* then handle any initialization relevant to IT Mill Toolkit.
*/
public IMenuBar() {
// The superclass has a lot of relevant initialization
super();

// This method call of the Paintable interface sets the component
// style name in DOM tree
setStyleName(CLASSNAME);
}

/**
* This method must be implemented to update the client-side component from
* UIDL data received from server.
*
* This method is called when the page is loaded for the first time, and
* every time UI changes in the component are received from the server.
*/
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
// This call should be made first. Ensure correct implementation,
// and let the containing layout manage caption, etc.
if (client.updateComponent(this, uidl, true)) {
return;
}

// Save reference to server connection object to be able to send
// user interaction later
this.client = client;

// Save the UIDL identifier for the component
uidlId = uidl.getId();

// Empty the menu every time it receives new information
if (!this.getItems().isEmpty()) {
this.clearItems();
}

/* Get tree received from server and actualize it in the GWT-MenuBar */

// For GWT 1.5
// this.setAnimationEnabled(uidl.getBooleanAttribute("animationEnabled"));
UIDL items = uidl.getChildUIDL(1);
Iterator itr = items.getChildIterator();
Stack iteratorStack = new Stack();
Stack menuStack = new Stack();
MenuBar currentMenu = this;

// Construct an empty command to be used when the item has no command
// associated
Command emptyCommand = new Command() {
public void execute() {
}
};

while (itr.hasNext()) {
UIDL item = (UIDL) itr.next();
MenuItem menuItem = null; // For receiving the item

String itemText = item.getStringAttribute("text");
final int itemId = item.getIntAttribute("id");

boolean itemHasCommand = item.getBooleanAttribute("command");

// Construct html from the text and the optional icon
if (!item.hasAttribute("icon")) {
itemText = "<p>" + itemText + "</p>";
} else {
itemText = "<p>"
+ "<img src=\""
+ client.translateToolkitUri(item
.getStringAttribute("icon")) + "\"</img>"
+ itemText + "</p>";
}

// Check if we need to attach a command to this item
if (itemHasCommand) {
// Construct a command that fires onMenuClick(int) with the
// item's id-number
Command normalCommand = new Command() {
public void execute() {
hostReference.onMenuClick(itemId);
}
};

menuItem = currentMenu.addItem(itemText, true, normalCommand);

} else {
menuItem = currentMenu.addItem(itemText, true, emptyCommand);
}

if (item.getChildCount() > 0) {
menuStack.push(currentMenu);
iteratorStack.push(itr);
itr = item.getChildIterator();
currentMenu = new MenuBar(true);
menuItem.setSubMenu(currentMenu);
}

if (!itr.hasNext() && !iteratorStack.empty()) {
itr = (Iterator) iteratorStack.pop();
currentMenu = (MenuBar) menuStack.pop();
}
}// while

}// updateFromUIDL

/**
* This is called by the items in the menu and it communicates the
* information to the server
*
* @param clickedItemId
* id of the item that was clicked
*/
public void onMenuClick(int clickedItemId) {
// Updating the state to the server can not be done before
// the server connection is known, i.e., before updateFromUIDL()
// has been called.
if (uidlId != null && client != null) {
// Communicate the user interaction parameters to server. This call
// will initiate an AJAX request to the server.
client.updateVariable(uidlId, "clickedId", clickedItemId, true);
}
}
}// class IMenuBar

+ 110
- 0
src/com/itmill/toolkit/tests/tickets/Ticket1598.java 查看文件

@@ -0,0 +1,110 @@
package com.itmill.toolkit.tests.tickets;

import java.util.ArrayList;
import java.util.List;

import com.itmill.toolkit.Application;
import com.itmill.toolkit.terminal.ThemeResource;
import com.itmill.toolkit.ui.MenuBar;
import com.itmill.toolkit.ui.Window;
import com.itmill.toolkit.ui.MenuBar.Command;
import com.itmill.toolkit.ui.MenuBar.Item;

public class Ticket1598 extends Application {

Window main = new Window("MenuBar test");

final MenuBar menuBar = new MenuBar();

public void init() {
setMainWindow(main);
setTheme("default");

List itemList = new ArrayList();
// Populate the menubar
for (int i = 0; i < 5; i++) {
itemList.add(menuBar.addItem(new String("Menu " + i), null, null));
}

Item first = (Item) itemList.get(0);

for (int i = 0; i < 5; i++) {
first.addItem(new String("Submenu item" + i), null, new Command() {

public void menuSelected(Item selected) {
main.showNotification("Action " + selected.getText());
}
});
}

Item firstSecond = (Item) first.getChildren().get(1);

for (int i = 0; i < 3; i++) {
firstSecond.addItem(new String("Subsubmenu item" + i), null,
new Command() {

public void menuSelected(Item selected) {
main.showNotification("Action "
+ selected.getText());
}
});
}

Item second = (Item) menuBar.getItems().get(1);

for (int i = 0; i < 5; i++) {
second.addItem(new String("Second submenu item" + i), null,
new Command() {

public void menuSelected(Item selected) {
main.showNotification("Action "
+ selected.getText());
}
});
}

Item third = (Item) menuBar.getItems().get(2);
third.setIcon(new ThemeResource("icons/16/document.png"));

for (int i = 2; i <= 3; i++)
((Item) menuBar.getItems().get(i)).setCommand(new Command() {

public void menuSelected(Item selectedItem) {
main.showNotification("Action " + selectedItem.getText());
}
});

final Item fourth = (Item) menuBar.getItems().get(3);
fourth.setText("Toggle animation");

fourth.setCommand(new Command() {
public void menuSelected(Item selected) {
menuBar
.addItemBefore("No animation yet...", null, null,
fourth);
// menuBar.setAnimation(!menuBar.hasAnimation());
}
});

final Item last = (Item) menuBar.getItems().get(menuBar.getSize() - 1);
last.setText("Remove me!");

// A command for removing the selected menuitem
Command removeCommand = new Command() {

public void menuSelected(Item selected) {
Item parent = selected.getParent();
if (parent != null) {
parent.removeChild(selected);
} else {
menuBar.removeItem(selected);
}
}
};

last.setCommand(removeCommand);

main.addComponent(menuBar);

}
}

+ 511
- 0
src/com/itmill/toolkit/ui/MenuBar.java 查看文件

@@ -0,0 +1,511 @@
package com.itmill.toolkit.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import com.itmill.toolkit.terminal.PaintException;
import com.itmill.toolkit.terminal.PaintTarget;
import com.itmill.toolkit.terminal.Resource;

/**
* The top-level menu class. This can contain MenuItems, which in turn can
* contain Submenus and MenuCommands.
*
*/
public class MenuBar extends AbstractComponent {

// Items of the top-level menu
private List menuItems;

// Number of items in this menu
private static int numberOfItems = 0;

private boolean animationEnabled;

/** Tag is the UIDL element name for client-server communications. */
public java.lang.String getTag() {
return "menubar";
}

/** Paint (serialize) the component for the client. */
public void paintContent(PaintTarget target) throws PaintException {

// Superclass writes any common attributes in the paint target.
super.paintContent(target);

// Stack for list iterators
Stack iteratorStack = new Stack();

target.startTag("options");
target.addAttribute("animationEnabled", animationEnabled);
target.endTag("options");
target.startTag("items");

Iterator itr = menuItems.iterator();

// This generates the tree from the contents of the menu
while (itr.hasNext()) {

Item item = (Item) itr.next();

target.startTag("item");

target.addAttribute("text", item.getText());
target.addAttribute("id", item.getId());

Command command = item.getCommand();
if (command != null) {
target.addAttribute("command", true);
} else {
target.addAttribute("command", false);
}

Resource icon = item.getIcon();
if (icon != null) {
target.addAttribute("icon", icon);
}

if (item.hasChildren()) {
iteratorStack.push(itr); // For later use

// Go through the children
itr = item.getChildren().iterator();
} else {
target.endTag("item"); // Item had no children, end description
}

if (!itr.hasNext() && !iteratorStack.empty()) { // The end submenu
itr = (Iterator) iteratorStack.pop();
target.endTag("item");
}

}

target.endTag("items");
}

/** Deserialize changes received from client. */
public void changeVariables(Object source, Map variables) {
Stack items = new Stack();
boolean found = false;

if (variables.containsKey("clickedId")) {

Integer clickedId = (Integer) variables.get("clickedId");
Iterator itr = this.getItems().iterator();
while (itr.hasNext()) {
items.push((Item) itr.next());
}

Item tmpItem = null;

// Go through all the items in the menu
while (!found && !items.empty()) {
tmpItem = (Item) items.pop();
found = (clickedId.intValue() == tmpItem.getId());

if (tmpItem.hasChildren()) {
itr = tmpItem.getChildren().iterator();
while (itr.hasNext()) {
items.push(itr.next());
}
}

}
// If we got the clicked item, launch the command.
if (found) {
tmpItem.getCommand().menuSelected(tmpItem);
}// while
}// if
}// changeVariables

/**
* Constructs an empty, horizontal menu
*/
public MenuBar() {
menuItems = new ArrayList();
animationEnabled = false;
}

/**
* Add a new item to the menubar. Icon and command can be null, but a
* caption must be given.
*
* @param caption
* the text for the menu item
* @param icon
* the icon for the menu item
* @param command
* the command for the menu item
* @throws IllegalArgumentException
*/
public MenuBar.Item addItem(String caption, Resource icon,
MenuBar.Command command) {
if (caption == null) {
throw new IllegalArgumentException("caption cannot be null");
}
Item newItem = new Item(caption, icon, command);
menuItems.add(newItem);
requestRepaint();

return newItem;

}

/**
* Add an item before some item. If the given item does not exist the item
* is added at the end of the menu. Icon and command can be null, but a
* caption must be given.
*
* @param caption
* the text for the menu item
* @param icon
* the icon for the menu item
* @param command
* the command for the menu item
* @param itemToAddBefore
* the item that will be after the new item
* @throws IllegalArgumentException
*/
public MenuBar.Item addItemBefore(String caption, Resource icon,
MenuBar.Command command, MenuBar.Item itemToAddBefore) {
if (caption == null) {
throw new IllegalArgumentException("caption cannot be null");
}

Item newItem = new Item(caption, icon, command);
if (menuItems.contains(itemToAddBefore)) {
int index = menuItems.indexOf(itemToAddBefore);
menuItems.add(index, newItem);

} else {
menuItems.add(newItem);
}

requestRepaint();

return newItem;
}

/**
* Returns a list with all the MenuItem objects in the menubar
*
* @return a list containing the MenuItem objects in the menubar
*/
public java.util.List getItems() {
return menuItems;
}

/**
* Remove first occurrence the specified item from the main menu
*
* @param item
* The item to be removed
*/
public void removeItem(MenuBar.Item item) {
if (item != null) {
menuItems.remove(item);
}
requestRepaint();
}

/**
* Empty the menubar
*/
public void removeItems() {
menuItems.clear();
requestRepaint();
}

/**
* Returns the size of the menu.
*
* @return The size of the menu
*/
public int getSize() {
return menuItems.size();
}

/**
* Enable or disable animated menubar appearance. Animation is disabled by
* default.
*
* @param hasAnimation
*/
public void setAnimation(boolean animation) {
animationEnabled = animation;
}

/**
* Returns true if the animation is enabled. Animation of this class is
* disabled by default.
*
* @return true if the animation is enabled
*
*/
public boolean hasAnimation() {
return animationEnabled;
}

/**
* This interface contains the layer for menu commands of the MenuBar class .
* It's method will fire when the user clicks on the containing MenuItem.
* The selected item is given as an argument.
*/
public interface Command {
public void menuSelected(MenuBar.Item selectedItem);
}

/**
* A composite class for menu items and submenus. You can set commands to be
* fired on user click by implementing the MenuBar.Command interface.
*
*/
public class Item {

/** Private members * */
private int itsId;
private Command itsCommand;
private String itsText;
private List itsChildren;
private Resource itsIcon;
private Item itsParent;

/**
* Constructs a new menu item that can optionally have an icon and a
* command associated with it. Icon and command can be null, but a
* caption must be given.
*
* @param text
* The text associated with the command
* @param command
* The command to be fired
* @throws IllegalArgumentException
*/
public Item(String caption, Resource icon, MenuBar.Command command) {
if (caption == null) {
throw new IllegalArgumentException("caption cannot be null");
}
itsId = ++numberOfItems;
itsText = caption;
itsIcon = icon;
itsCommand = command;
}

/**
* Checks if the item has children (if it is a submenu).
*
* @return True if this item has children
*/
public boolean hasChildren() {
return itsChildren != null;
}

/**
* Add a new item inside this item, thus creating a submenu. Icon and
* command can be null, but a caption must be given.
*
* @param caption
* the text for the menu item
* @param icon
* the icon for the menu item
* @param command
* the command for the menu item
*/
public MenuBar.Item addItem(String caption, Resource icon,
MenuBar.Command command) {
if (caption == null) {
throw new IllegalArgumentException("caption cannot be null");
}

if (itsChildren == null) {
itsChildren = new ArrayList();
}

Item newItem = new Item(caption, icon, command);

// The only place where the parent is set
newItem.setParent(this);
itsChildren.add(newItem);

requestRepaint();

return newItem;
}

/**
* Add an item before some item. If the given item does not exist the
* item is added at the end of the menu. Icon and command can be null,
* but a caption must be given.
*
* @param caption
* the text for the menu item
* @param icon
* the icon for the menu item
* @param command
* the command for the menu item
* @param itemToAddBefore
* the item that will be after the new item
*
*/
public MenuBar.Item addItemBefore(String caption, Resource icon,
MenuBar.Command command, MenuBar.Item itemToAddBefore) {

Item newItem = null;

if (hasChildren() && itsChildren.contains(itemToAddBefore)) {
int index = itsChildren.indexOf(itemToAddBefore);
newItem = new Item(caption, icon, command);
newItem.setParent(this);
itsChildren.add(index, newItem);

} else {
newItem = addItem(caption, icon, command);
}

requestRepaint();

return newItem;
}

/**
* For the associated command.
*
* @return The associated command, or null if there is none
*/
public Command getCommand() {
return itsCommand;
}

/**
* Gets the objects icon.
*
* @return The icon of the item, null if the item doesn't have an icon
*/
public Resource getIcon() {
return itsIcon;
}

/**
* For the containing item. This will return null if the item is in the
* top-level menubar.
*
* @return The containing MenuBar.MenuItem, or null if there is none
*/
public MenuBar.Item getParent() {
return itsParent;
}

/**
* This will return the children of this item or null if there are none.
*
* @return List of children items, or null if there are none
*/
public java.util.List getChildren() {
return itsChildren;
}

/**
* Gets the objects text
*
* @return The text
*/
public java.lang.String getText() {
return itsText;
}

/**
* Returns the number of children.
*
* @return The number of child items
*/
public int getSize() {
return itsChildren.size();
}

/**
* Get the unique identifier for this item.
*
* @return The id of this item
*/
public int getId() {
return itsId;
}

/**
* Set the command for this item. Set null to remove.
*
* @param command
* The MenuCommand of this item
*/
public void setCommand(MenuBar.Command command) {
itsCommand = command;
}

/**
* Sets the icon. Set null to remove.
*
* @param icon
* The icon for this item
*/
public void setIcon(Resource icon) {
itsIcon = icon;
requestRepaint();
}

/**
* Set the text of this object.
*
* @param text
* Text for this object
*/
public void setText(java.lang.String text) {
if (text != null) {
itsText = text;
}
requestRepaint();
}

/**
* Remove the first occurrence of the item.
*
* @param item
* The item to be removed
*/
public void removeChild(MenuBar.Item item) {
if (item != null && itsChildren != null) {
itsChildren.remove(item);
if (itsChildren.isEmpty()) {
itsChildren = null;
}
}
requestRepaint();
}

/**
* Empty the list of children items.
*/
public void removeChildren() {
if (itsChildren != null) {
itsChildren.clear();
itsChildren = null;
}
requestRepaint();
}

/**
* Set the parent of this item. This is called by the addItem method.
*
* @param parent
* The parent item
*/
protected void setParent(MenuBar.Item parent) {
itsParent = parent;
}

}// class MenuItem

}// class MenuBar

正在加载...
取消
保存