001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.ui;
039:
040: import java.util.Iterator;
041: import java.util.Map;
042:
043: import org.millstone.base.terminal.PaintException;
044: import org.millstone.base.terminal.PaintTarget;
045: import org.millstone.base.terminal.Sizeable;
046: import org.millstone.base.terminal.Scrollable;
047:
048: /** Panel - a simple single component container.
049: * @author IT Mill Ltd.
050: * @version 3.1.1
051: * @since 3.0
052: */
053: public class Panel extends AbstractComponentContainer implements
054: Sizeable, Scrollable,
055: ComponentContainer.ComponentAttachListener,
056: ComponentContainer.ComponentDetachListener {
057:
058: /** Layout of the panel */
059: private Layout layout;
060:
061: /** Width of the panel or -1 if unspecified */
062: private int width = -1;
063:
064: /** Height of the panel or -1 if unspecified */
065: private int height = -1;
066:
067: /** Width unit */
068: private int widthUnit = Sizeable.UNITS_PIXELS;
069:
070: /** Height unit */
071: private int heightUnit = Sizeable.UNITS_PIXELS;
072:
073: /** Scroll X position */
074: private int scrollOffsetX = 0;
075:
076: /** Scroll Y position */
077: private int scrollOffsetY = 0;
078:
079: /** Scrolling mode */
080: private boolean scrollable = false;
081:
082: /** Create new empty panel.
083: * Ordered layout is used.
084: */
085: public Panel() {
086: this (new OrderedLayout());
087: }
088:
089: /** Create new empty panel with given layout.
090: * Layout must be non-null.
091: *
092: * @param layout The layout used in the panel.
093: */
094: public Panel(Layout layout) {
095: setLayout(layout);
096: }
097:
098: /** Create new empty panel with caption.
099: * Ordered layout is used.
100: *
101: * @param caption The caption used in the panel.
102: */
103: public Panel(String caption) {
104: this (caption, new OrderedLayout());
105: }
106:
107: /** Create new empty panel with caption.
108: *
109: * @param caption The caption of the panel.
110: * @param layout The layout used in the panel.
111: */
112: public Panel(String caption, Layout layout) {
113: this (layout);
114: setCaption(caption);
115: }
116:
117: /** Get the current layout of the panel.
118: * @return Current layout of the panel.
119: */
120: public Layout getLayout() {
121: return this .layout;
122: }
123:
124: /** Set the layout of the panel.
125: * All the components are moved to new layout.
126: *
127: * @param layout New layout of the panel.
128: */
129: public void setLayout(Layout layout) {
130:
131: // Only allow non-null layouts
132: if (layout == null)
133: layout = new OrderedLayout();
134:
135: // Set the panel to be parent for the layout
136: layout.setParent(this );
137: dependsOn(layout);
138:
139: // If panel already contains a layout, move the contents to new one
140: // and detach old layout from the panel
141: if (this .layout != null) {
142: layout.moveComponentsFrom(this .layout);
143: removeDirectDependency(this .layout);
144: this .layout.setParent(null);
145: }
146:
147: // Remove the event listeners from the old layout
148: if (this .layout != null) {
149: this .layout
150: .removeListener((ComponentContainer.ComponentAttachListener) this );
151: this .layout
152: .removeListener((ComponentContainer.ComponentDetachListener) this );
153: }
154:
155: // Set the new layout
156: this .layout = layout;
157:
158: // Add event listeners for new layout
159: layout
160: .addListener((ComponentContainer.ComponentAttachListener) this );
161: layout
162: .addListener((ComponentContainer.ComponentDetachListener) this );
163: }
164:
165: /** Paint the content of this component.
166: * @param event PaintEvent.
167: * @throws PaintException The paint operation failed.
168: */
169: public void paintContent(PaintTarget target) throws PaintException {
170: layout.paint(target);
171: target.addVariable(this , "height", getHeight());
172: target.addVariable(this , "width", getWidth());
173: if (isScrollable()) {
174: target.addVariable(this , "scrollleft", getScrollOffsetX());
175: target.addVariable(this , "scrolldown", getScrollOffsetY());
176: }
177: }
178:
179: /** Get component UIDL tag.
180: * @return Component UIDL tag as string.
181: */
182: public String getTag() {
183: return "panel";
184: }
185:
186: /** Add a component into this container.
187: * @param c The component to be added.
188: */
189: public void addComponent(Component c) {
190: layout.addComponent(c);
191: // No repaint request is made as we except the underlaying container to
192: // request repaints
193: }
194:
195: /** Remove a component from this container.
196: * @param c The component to be added.
197: */
198: public void removeComponent(Component c) {
199: layout.removeComponent(c);
200: // No repaint request is made as we except the underlaying container to
201: // request repaints
202: }
203:
204: /** Get component container iterator for going trough all the components in the container.
205: * @return Iterator of the components inside the container.
206: */
207: public Iterator getComponentIterator() {
208: return layout.getComponentIterator();
209: }
210:
211: /**
212: * @return The height in pixels or negative value if not assigned.
213: */
214: public int getHeight() {
215: return height;
216: }
217:
218: /**
219: * @return The width in pixels or negative value if not assigned.
220: */
221: public int getWidth() {
222: return width;
223: }
224:
225: /** Sets the height in pixels.
226: * Use negative value to let the client decide the height.
227: * @param height The height to set
228: */
229: public void setHeight(int height) {
230: this .height = height;
231: requestRepaint();
232: }
233:
234: /** Sets the width in pixels.
235: * Use negative value to allow the client decide the width.
236: * @param width The width to set
237: */
238: public void setWidth(int width) {
239: this .width = width;
240: requestRepaint();
241: }
242:
243: /**
244: * @see org.millstone.base.terminal.VariableOwner#changeVariables(Object, Map)
245: */
246: public void changeVariables(Object source, Map variables) {
247: super .changeVariables(source, variables);
248:
249: // Get new size
250: Integer newWidth = (Integer) variables.get("width");
251: Integer newHeight = (Integer) variables.get("height");
252: if (newWidth != null && newWidth.intValue() != getWidth())
253: setWidth(newWidth.intValue());
254: if (newHeight != null && newHeight.intValue() != getHeight())
255: setHeight(newHeight.intValue());
256:
257: // Scrolling
258: Integer newScrollX = (Integer) variables.get("scrollleft");
259: Integer newScrollY = (Integer) variables.get("scrolldown");
260: if (newScrollX != null
261: && newScrollX.intValue() != getScrollOffsetX())
262: setScrollOffsetX(newScrollX.intValue());
263: if (newScrollY != null
264: && newScrollY.intValue() != getScrollOffsetY())
265: setScrollOffsetY(newScrollY.intValue());
266: }
267:
268: /**
269: * @see org.millstone.base.terminal.Sizeable#getHeightUnits()
270: */
271: public int getHeightUnits() {
272: return heightUnit;
273: }
274:
275: /**
276: * @see org.millstone.base.terminal.Sizeable#getWidthUnits()
277: */
278: public int getWidthUnits() {
279: return widthUnit;
280: }
281:
282: /** Set height units.
283: * Panel supports only Sizeable.UNITS_PIXELS and this is ignored.
284: * @see org. millstone.base.terminal.Sizeable#setHeightUnits(int)
285: */
286: public void setHeightUnits(int units) {
287: // Ignored
288: }
289:
290: /** Set width units.
291: * Panel supports only Sizeable.UNITS_PIXELS, and this is ignored.
292: * @see org.millstone.base.terminal.Sizeable#setWidthUnits(int)
293: */
294: public void setWidthUnits(int units) {
295: // Ignored
296: }
297:
298: /* Scrolling functionality */
299:
300: /* Documented in interface */
301: public int getScrollOffsetX() {
302: return scrollOffsetX;
303: }
304:
305: /* Documented in interface */
306: public int getScrollOffsetY() {
307: return scrollOffsetY;
308: }
309:
310: /* Documented in interface */
311: public boolean isScrollable() {
312: return scrollable;
313: }
314:
315: /* Documented in interface */
316: public void setScrollable(boolean isScrollingEnabled) {
317: if (scrollable != isScrollingEnabled) {
318: scrollable = isScrollingEnabled;
319: requestRepaint();
320: }
321: }
322:
323: /* Documented in interface */
324: public void setScrollOffsetX(int pixelsScrolledLeft) {
325: if (pixelsScrolledLeft < 0)
326: throw new IllegalArgumentException(
327: "Scroll offset must be at least 0");
328: if (this .scrollOffsetX != pixelsScrolledLeft) {
329: scrollOffsetX = pixelsScrolledLeft;
330: requestRepaint();
331: }
332: }
333:
334: /* Documented in interface */
335: public void setScrollOffsetY(int pixelsScrolledDown) {
336: if (pixelsScrolledDown < 0)
337: throw new IllegalArgumentException(
338: "Scroll offset must be at least 0");
339: if (this .scrollOffsetY != pixelsScrolledDown) {
340: scrollOffsetY = pixelsScrolledDown;
341: requestRepaint();
342: }
343: }
344:
345: /* Documented in superclass */
346: public void replaceComponent(Component oldComponent,
347: Component newComponent) {
348:
349: layout.replaceComponent(oldComponent, newComponent);
350: }
351:
352: /** Pass the events from underlying layout forwards.
353: * @see org.millstone.base.ui.ComponentContainer.ComponentAttachListener#componentAttachedToContainer(org.millstone.base.ui.ComponentContainer.ComponentAttachEvent)
354: */
355: public void componentAttachedToContainer(ComponentAttachEvent event) {
356: if (event.getContainer() == layout)
357: fireComponentAttachEvent(event.getAttachedComponent());
358: }
359:
360: /** Pass the events from underlying layout forwards.
361: * @see org.millstone.base.ui.ComponentContainer.ComponentDetachListener#componentDetachedFromContainer(org.millstone.base.ui.ComponentContainer.ComponentDetachEvent)
362: */
363: public void componentDetachedFromContainer(
364: ComponentDetachEvent event) {
365: if (event.getContainer() == layout)
366: fireComponentDetachEvent(event.getDetachedComponent());
367: }
368:
369: /*
370: * @see org.millstone.base.ui.Component#attach()
371: */
372: public void attach() {
373: if (layout != null)
374: layout.attach();
375: }
376:
377: /*
378: * @see org.millstone.base.ui.Component#detach()
379: */
380: public void detach() {
381: if (layout != null)
382: layout.detach();
383: }
384:
385: /*
386: * @see org.millstone.base.ui.ComponentContainer#removeAllComponents()
387: */
388: public void removeAllComponents() {
389: layout.removeAllComponents();
390: }
391:
392: }
|