Java tutorial
/** Exhibit A - UIRF Open-source Based Public Software License. * * The contents of this file are subject to the UIRF Open-source Based * Public Software License(the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * openelis.uhl.uiowa.edu * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is OpenELIS code. * * The Initial Developer of the Original Code is The University of Iowa. * Portions created by The University of Iowa are Copyright 2006-2008. All * Rights Reserved. * * Contributor(s): ______________________________________. * * Alternatively, the contents of this file marked * "Separately-Licensed" may be used under the terms of a UIRF Software * license ("UIRF Software License"), in which case the provisions of a * UIRF Software License are applicable instead of those above. */ package org.openelis.gwt.widget.table; import java.util.ArrayList; import org.openelis.gwt.event.ActionEvent; import org.openelis.gwt.event.ActionHandler; import org.openelis.gwt.widget.CheckBox; import org.openelis.gwt.widget.MenuItem; import org.openelis.gwt.widget.MenuPanel; import org.openelis.gwt.widget.QueryFieldUtil; import org.openelis.gwt.widget.TextBox; import org.openelis.gwt.widget.table.event.SortEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.HasClickHandlers; import com.google.gwt.event.dom.client.HasMouseDownHandlers; import com.google.gwt.event.dom.client.HasMouseMoveHandlers; import com.google.gwt.event.dom.client.HasMouseOutHandlers; import com.google.gwt.event.dom.client.HasMouseOverHandlers; import com.google.gwt.event.dom.client.HasMouseUpHandlers; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; public class TableHeaderBar extends Composite implements MouseMoveHandler, MouseDownHandler, MouseUpHandler, CloseHandler<PopupPanel>, ActionHandler<MenuItem.Action>, ClickHandler, HasMouseOutHandlers { public static String headerStyle = "Header"; public static String headerCellStyle = "HeaderCell"; public ArrayList<Label> hLabels = new ArrayList<Label>(); public ArrayList<MenuItem> hMenus = new ArrayList<MenuItem>(); public ArrayList<HorizontalPanel> headers = new ArrayList<HorizontalPanel>(); protected ArrayList<TableColumn> columns; protected boolean resizing; protected int startx; protected int resizeColumn1 = -1; protected int tableCol1 = -1; protected TableWidget controller; public boolean doFilter; public boolean doQuery; private FlexTable bar = new FlexTable(); private TableHeaderBar source = this; protected MenuItem menuItem = null; protected PopupPanel pop = new PopupPanel(true); public TableHeaderBar() { initWidget(bar); } public class BarContainer extends AbsolutePanel implements HasMouseDownHandlers, HasMouseUpHandlers, HasMouseMoveHandlers { public BarContainer() { sinkEvents(Event.MOUSEEVENTS); } public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) { return addDomHandler(handler, MouseDownEvent.getType()); } public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) { return addDomHandler(handler, MouseUpEvent.getType()); } public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) { return addDomHandler(handler, MouseMoveEvent.getType()); } } public class ListenContainer extends HorizontalPanel implements HasMouseOverHandlers, HasMouseOutHandlers, MouseOverHandler, MouseOutHandler, HasClickHandlers, ClickHandler, CloseHandler<PopupPanel> { public void onMouseOver(MouseOverEvent event) { int index = headers.indexOf(this); if (hMenus.get(index) == null) { pop.hide(); menuItem = null; return; } if (menuItem == hMenus.get(index)) return; menuItem = hMenus.get(index); int left = this.getAbsoluteLeft() + this.getOffsetWidth() - 19; if (left > controller.view.cellView.getAbsoluteLeft() + controller.view.cellView.getOffsetWidth()) left = controller.view.cellView.getAbsoluteLeft() + controller.view.cellView.getOffsetWidth() - 19; pop.addCloseHandler(new CloseHandler<PopupPanel>() { public void onClose(CloseEvent<PopupPanel> event) { menuItem = null; } }); pop.setWidget(menuItem); pop.setPopupPosition(left, this.getAbsoluteTop()); pop.show(); } /** * Catches mouses Events for resizing columns. */ public void onMouseOut(MouseOutEvent event) { //Window.alert(""+event.getRelativeY(getElement())); if (pop.isShowing() && !menuItem.popShowing && ((event.getRelativeX(((Widget) event.getSource()).getElement()) <= 0 || event.getRelativeX(((Widget) event.getSource()).getElement()) >= getOffsetWidth()) || (event.getRelativeY(((Widget) event.getSource()).getElement()) <= 0 || event.getRelativeY( ((Widget) event.getSource()).getElement()) >= getOffsetHeight()))) { //RootPanel.get().remove(menuItem); pop.hide(); menuItem = null; } } public void onClose(CloseEvent<PopupPanel> event) { if (menuItem != null) { //RootPanel.get().remove(menuItem); pop.hide(); menuItem = null; } } public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) { return addDomHandler(handler, MouseOverEvent.getType()); } public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) { return addDomHandler(handler, MouseOutEvent.getType()); } public HandlerRegistration addClickHandler(ClickHandler handler) { return addDomHandler(handler, ClickEvent.getType()); } public void onClick(ClickEvent event) { //menuItem.onClick(event); } } public void init(TableWidget controller) { setStyleName("topHeaderBar"); this.controller = controller; this.columns = controller.columns; bar.setCellSpacing(0); bar.setCellPadding(0); for (TableColumn column : columns) { ListenContainer header = new ListenContainer(); header.setSpacing(0); headers.add(header); Label headerLabel = new Label(column.getHeader()); hLabels.add(headerLabel); DOM.setStyleAttribute(header.getElement(), "overflow", "hidden"); DOM.setStyleAttribute(header.getElement(), "overflowX", "hidden"); headerLabel.addStyleName("HeaderLabel"); DOM.setStyleAttribute(headerLabel.getElement(), "overflowX", "hidden"); DOM.setStyleAttribute(headerLabel.getElement(), "overflow", "hidden"); headerLabel.setWordWrap(false); header.add(headerLabel); header.setCellWidth(headerLabel, "100%"); header.add(headerLabel); MenuItem menuItem = null; if (column.getSortable() || column.getFilterable()) { AbsolutePanel wid = new AbsolutePanel(); wid.setHeight("18px"); wid.setWidth("16px"); menuItem = new MenuItem(wid); menuItem.menuItemsPanel = new MenuPanel("vertical"); menuItem.menuItemsPanel.setStyleName("topHeaderContainer"); menuItem.addActionHandler(this); menuItem.addMouseOutHandler(header); header.addMouseOverHandler(header); header.addMouseOutHandler(header); menuItem.pop.addCloseHandler(header); menuItem.enable(true); menuItem.setStyleName("HeaderDropdownButton"); } hMenus.add(menuItem); BarContainer barc = new BarContainer(); barc.addMouseDownHandler(this); barc.addMouseUpHandler(this); barc.addMouseMoveHandler(this); AbsolutePanel ap3 = new AbsolutePanel(); ap3.addStyleName("HeaderBarPad"); barc.add(ap3); header.add(barc); bar.setWidget(0, columns.indexOf(column), header); bar.getCellFormatter().setHeight(0, columns.indexOf(column), "18px"); bar.getCellFormatter().setStyleName(0, columns.indexOf(column), "Header"); } sizeHeader(); addMouseOutHandler(new MouseOutHandler() { public void onMouseOut(MouseOutEvent event) { if (pop.isShowing()) { if ((event.getRelativeX(getElement()) <= 0 || event.getRelativeX(getElement()) >= getOffsetWidth()) || (event.getRelativeY(getElement()) <= 0 || event.getRelativeY(getElement()) >= getOffsetHeight())) { pop.hide(); menuItem = null; } } } }); } public void setHeaders(String[] headers) { for (int i = 0; i < headers.length; i++) { hLabels.get(i).setText(headers[i]); } } /** * Catches mouses Events for resizing columns. */ public void onMouseDown(MouseDownEvent event) { Widget sender = (Widget) event.getSource(); // TODO Auto-generated method stub resizing = true; startx = sender.getAbsoluteLeft(); resizeColumn1 = headers.indexOf(sender.getParent()); tableCol1 = resizeColumn1; if (columns.get(tableCol1).getFixedWidth()) { resizing = false; resizeColumn1 = -1; tableCol1 = -1; return; } if (pop.isShowing()) { pop.hide(); menuItem = null; } //menuItem.removeFromParent(); FocusPanel bar = new FocusPanel(); bar.addMouseUpHandler(this); bar.addMouseDownHandler(this); bar.addMouseMoveHandler(this); bar.setHeight((controller.view.cellView.getOffsetHeight() + 17) + "px"); bar.setWidth("1px"); DOM.setStyleAttribute(bar.getElement(), "background", "red"); DOM.setStyleAttribute(bar.getElement(), "position", "absolute"); DOM.setStyleAttribute(bar.getElement(), "left", sender.getAbsoluteLeft() + "px"); DOM.setStyleAttribute(bar.getElement(), "top", sender.getAbsoluteTop() + "px"); RootPanel.get().add(bar); DOM.setCapture(bar.getElement()); DOM.setStyleAttribute(bar.getElement(), "zIndex", "1000"); } /** * Catches mouses Events for resizing columns. */ public void onMouseMove(MouseMoveEvent event) { Widget sender = (Widget) event.getSource(); if (resizing) { int colA = columns.get(tableCol1).getCurrentWidth() + (sender.getAbsoluteLeft() - startx); int pad = 5; if (columns.get(tableCol1).sortable || columns.get(tableCol1).filterable) pad = 5; if ((event.getX() < 0 && (colA - pad) <= columns.get(tableCol1).getMinWidth())) return; DOM.setStyleAttribute(sender.getElement(), "left", (DOM.getAbsoluteLeft(sender.getElement()) + (event.getX())) + "px"); } } /** * Catches mouses Events for resizing columns. */ public void onMouseUp(MouseUpEvent event) { Widget sender = (Widget) event.getSource(); if (resizing) { DOM.releaseCapture(sender.getElement()); int colWidth = columns.get(tableCol1).getCurrentWidth() + (sender.getAbsoluteLeft() - startx); int scrollWidth = 0; for (int i = 0; i < headers.size(); i++) { if (tableCol1 != i) scrollWidth += columns.get(i).getCurrentWidth() + 3; } if (scrollWidth + colWidth < controller.getTableWidth()) colWidth = controller.getTableWidth() - scrollWidth - 3; columns.get(tableCol1).setCurrentWidth(colWidth); resizing = false; RootPanel.get().remove(sender); DeferredCommand.addCommand(new Command() { public void execute() { sizeHeader(); for (int j = 0; j < controller.view.table.getRowCount(); j++) { for (int i = 0; i < columns.size(); i++) { controller.view.table.getFlexCellFormatter().setWidth(j, i, (columns.get(i).getCurrentWidth()) + "px"); if (!(controller.columns.get(i).getColumnWidget() instanceof CheckBox)) controller.view.table.getWidget(j, i) .setWidth((columns.get(i).getCurrentWidth()) + "px"); } } } }); } } public void sizeHeader() { DeferredCommand.addCommand(new Command() { public void execute() { int scrollWidth = 0; if (columns.size() == 0) return; for (int i = 0; i < headers.size(); i++) { scrollWidth += columns.get(i).getCurrentWidth(); HorizontalPanel header = headers.get(i); header.setWidth((columns.get(i).currentWidth + 2) + "px"); int pad = 5; if (columns.get(i).sortable || columns.get(i).filterable) pad = 5; if (columns.get(i).currentWidth - pad < columns.get(i).getMinWidth()) { hLabels.get(i).setWidth(columns.get(i).getMinWidth() + "px"); } else { hLabels.get(i).setWidth((columns.get(i).currentWidth - pad) + "px"); } } controller.view.cellView.setScrollWidth((scrollWidth + (controller.columns.size() * 3)) + "px"); } }); } public void onAction(ActionEvent<MenuItem.Action> event) { if (event.getAction() == MenuItem.Action.OPENING) { final int index = hMenus.indexOf((MenuItem) event.getData()); final TableColumn col = (TableColumn) controller.columns.get(index); if (col.filterDisplayed) ((MenuItem) event.getSource()).menuItemsPanel.clear(); if (col.getSortable()) { MenuItem item = new MenuItem("Ascending", new Label("Ascending"), ""); item.setStyleName("topHeaderRowContainer"); ((MenuItem) event.getData()).menuItemsPanel.add(item); item.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { controller.sort(index, SortEvent.SortDirection.ASCENDING); } }); item.enable(true); item = new MenuItem("Descending", new Label("Descending"), ""); item.setStyleName("topHeaderRowContainer"); ((MenuItem) event.getData()).menuItemsPanel.add(item); item.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { controller.sort(index, SortEvent.SortDirection.DESCENDING); } }); item.enable(true); if (col.filterable) { ((MenuItem) event.getData()).menuItemsPanel.add(new HTML("<hr/>")); } } if (col.filterable) { MenuItem filterMenu = new MenuItem("", new Label("Filters"), ""); filterMenu.popPosition = MenuItem.PopPosition.BESIDE; filterMenu.menuItemsPanel = new MenuPanel("vertical"); filterMenu.menuItemsPanel.setStyleName("topHeaderContainer"); ArrayList<Filter> filters = col.getFilters(); for (Filter filter : filters) { String filtered = "Unchecked"; if (filter.filtered) filtered = "Checked"; MenuItem item = new MenuItem(filtered, filter.display, ""); item.addClickHandler(this); item.setStyleName("topHeaderRowContainer"); //item.addMouseListener((MouseListener)ClassFactory.forName("HoverListener")); filterMenu.menuItemsPanel.add(item); item.args = new Object[] { filter, index }; item.enable(true); } filterMenu.pop.addCloseHandler(this); ((MenuItem) event.getData()).menuItemsPanel.add(filterMenu); filterMenu.enable(true); } if (col.queryable) { final TextBox entryText = new TextBox(); String checkState = "Unchecked"; if (col.query != null) { checkState = "Checked"; entryText.setText(col.query.queryString); } final MenuItem item = new MenuItem(checkState, entryText, ""); ((MenuItem) event.getData()).menuItemsPanel.add(item); ((MenuItem) event.getData()).pop.addCloseHandler(this); item.unsinkEvents(Event.ONCLICK); final TableColumn column = col; entryText.addKeyUpHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) { if (((TextBox) event.getSource()).getText().length() > 0) { doQuery = true; item.iconPanel.setStyleName("Checked"); //col.query = ((TextBox)event.getSource()).getText(); } else { doQuery = false; doFilter = true; item.iconPanel.setStyleName("Unchecked"); col.query = null; } if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { if (doQuery) { query(col, entryText.getText()); } else { col.query = null; applyQueryFilter(); } if (item.parent != null && item.parent.getParent() instanceof PopupPanel) ((PopupPanel) item.parent.getParent()).hide(); } } }); } col.filterDisplayed = true; } } public void onClose(CloseEvent<PopupPanel> event) { } public void onClick(ClickEvent event) { Widget sender = (Widget) event.getSource(); if (sender instanceof MenuItem) { doFilter = true; Filter filter = (Filter) ((MenuItem) sender).args[0]; TableColumn col = (TableColumn) controller.columns.get((((Integer) ((MenuItem) sender).args[1]))); filter.filtered = !filter.filtered; if (filter.filtered) ((MenuItem) sender).iconPanel.setStyleName("Checked"); else ((MenuItem) sender).iconPanel.setStyleName("Unchecked"); ArrayList<Filter> filters = col.getFilterList(); if (filter.obj == null) { for (Filter filt : filters) { if (filt.filtered) { filt.filtered = false; } } for (int i = 1; i < ((MenuItem) sender).parent.menuItems.size(); i++) ((MenuItem) sender).parent.menuItems.get(i).iconPanel.setStyleName("Unchecked"); filters.get(0).filtered = true; ((MenuItem) sender).parent.menuItems.get(0).iconPanel.setStyleName("Checked"); } else if (filter.filtered) { filters.get(0).filtered = false; ((MenuItem) sender).parent.menuItems.get(0).iconPanel.setStyleName("Unchecked"); } else { boolean setAll = true; for (Filter filt : filters) { if (filt.filtered) { setAll = false; break; } } if (setAll) { filters.get(0).filtered = true; ((MenuItem) sender).parent.menuItems.get(0).iconPanel.setStyleName("Checked"); } } col.setFilter(filters); applyQueryFilter(); //((MenuItem)sender).onMouseLeave(sender); } } private void applyQueryFilter() { for (TableDataRow row : controller.getData()) row.shown = true; for (TableColumn column : controller.columns) { if (((TableColumn) column).query != null) ((TableColumn) column).applyQueryFilter(); else column.applyFilter(); } controller.refresh(); controller.fireFilterEvent(); } public void query(TableColumn col, String query) { QueryFieldUtil qField = new QueryFieldUtil(); qField.parse(query); col.query = qField; applyQueryFilter(); } public static native String getUserAgent() /*-{ return navigator.userAgent.toLowerCase(); }-*/; public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) { return addDomHandler(handler, MouseOutEvent.getType()); } }