001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.sample.mail.client;
017:
018: import com.google.gwt.user.client.DOM;
019: import com.google.gwt.user.client.Element;
020: import com.google.gwt.user.client.Event;
021: import com.google.gwt.user.client.ui.AbstractImagePrototype;
022: import com.google.gwt.user.client.ui.Composite;
023: import com.google.gwt.user.client.ui.StackPanel;
024: import com.google.gwt.user.client.ui.Widget;
025:
026: /**
027: * A composite that contains the shortcut stack panel on the left side. The
028: * mailbox tree and shortcut lists don't actually do anything, but serve to show
029: * how you can construct an interface using
030: * {@link com.google.gwt.user.client.ui.StackPanel},
031: * {@link com.google.gwt.user.client.ui.Tree}, and other custom widgets.
032: */
033: public class Shortcuts extends Composite {
034:
035: /**
036: * An image bundle specifying the images for this Widget and aggragating
037: * images needed in child widgets.
038: */
039: public interface Images extends Contacts.Images, Mailboxes.Images {
040: AbstractImagePrototype contactsgroup();
041:
042: AbstractImagePrototype leftCorner();
043:
044: AbstractImagePrototype mailgroup();
045:
046: AbstractImagePrototype rightCorner();
047:
048: AbstractImagePrototype tasksgroup();
049: }
050:
051: private int nextHeaderIndex = 0;
052:
053: private StackPanel stackPanel = new StackPanel() {
054: @Override
055: public void onBrowserEvent(Event event) {
056: int oldIndex = getSelectedIndex();
057: super .onBrowserEvent(event);
058: int newIndex = getSelectedIndex();
059: if (oldIndex != newIndex) {
060: updateSelectedStyles(oldIndex, newIndex);
061: }
062: }
063: };
064:
065: /**
066: * Constructs a new shortcuts widget using the specified images.
067: *
068: * @param images a bundle that provides the images for this widget
069: */
070: public Shortcuts(Images images) {
071: // Create the groups within the stack panel.
072: add(images, new Mailboxes(images), images.mailgroup(), "Mail");
073: add(images, new Tasks(), images.tasksgroup(), "Tasks");
074: add(images, new Contacts(images), images.contactsgroup(),
075: "Contacts");
076:
077: initWidget(stackPanel);
078: }
079:
080: @Override
081: protected void onLoad() {
082: // Show the mailboxes group by default.
083: stackPanel.showStack(0);
084: updateSelectedStyles(-1, 0);
085: }
086:
087: private void add(Images images, Widget widget,
088: AbstractImagePrototype imageProto, String caption) {
089: widget.addStyleName("mail-StackContent");
090: stackPanel.add(widget, createHeaderHTML(images, imageProto,
091: caption), true);
092: }
093:
094: private String computeHeaderId(int index) {
095: return "header-" + this .hashCode() + "-" + index;
096: }
097:
098: /**
099: * Creates an HTML fragment that places an image & caption together, for use
100: * in a group header.
101: *
102: * @param imageProto an image prototype for an image
103: * @param caption the group caption
104: * @return the header HTML fragment
105: */
106: private String createHeaderHTML(Images images,
107: AbstractImagePrototype imageProto, String caption) {
108:
109: boolean isTop = (nextHeaderIndex == 0);
110: String cssId = computeHeaderId(nextHeaderIndex);
111: nextHeaderIndex++;
112:
113: String captionHTML = "<table class='caption' cellpadding='0' cellspacing='0'>"
114: + "<tr><td class='lcaption'>"
115: + imageProto.getHTML()
116: + "</td><td class='rcaption'><b style='white-space:nowrap'>"
117: + caption + "</b></td></tr></table>";
118:
119: return "<table id='" + cssId
120: + "' align='left' cellpadding='0' cellspacing='0'"
121: + (isTop ? " class='is-top'" : "") + "><tbody>"
122: + "<tr><td class='box-00'>"
123: + images.leftCorner().getHTML() + "</td>"
124: + "<td class='box-10'> </td>"
125: + "<td class='box-20'>"
126: + images.rightCorner().getHTML() + "</td>"
127: + "</tr><tr>" + "<td class='box-01'> </td>"
128: + "<td class='box-11'>" + captionHTML + "</td>"
129: + "<td class='box-21'> </td>"
130: + "</tr></tbody></table>";
131: }
132:
133: /**
134: * Example of using the DOM class to do CSS class name tricks that have
135: * become common to AJAX apps. In this case we add CSS class name for the
136: * stack panel item that is below the selected item.
137: */
138: private void updateSelectedStyles(int oldIndex, int newIndex) {
139: oldIndex++;
140: if (oldIndex > 0 && oldIndex < stackPanel.getWidgetCount()) {
141: Element elem = DOM
142: .getElementById(computeHeaderId(oldIndex));
143: DOM.setElementProperty(elem, "className", "");
144: }
145:
146: newIndex++;
147: if (newIndex > 0 && newIndex < stackPanel.getWidgetCount()) {
148: Element elem = DOM
149: .getElementById(computeHeaderId(newIndex));
150: DOM.setElementProperty(elem, "className",
151: "is-beneath-selected");
152: }
153: }
154: }
|