001: /*
002: * Copyright (C) 2005 Jeff Tassin
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.jeta.swingbuilder.gui.editor;
020:
021: import java.awt.BorderLayout;
022: import java.awt.Dimension;
023: import java.awt.FlowLayout;
024:
025: import javax.swing.AbstractButton;
026: import javax.swing.JButton;
027: import javax.swing.JPanel;
028:
029: import com.jeta.forms.gui.beans.JETABean;
030: import com.jeta.forms.gui.common.FormException;
031: import com.jeta.forms.gui.common.FormUtils;
032: import com.jeta.forms.gui.components.ComponentSource;
033: import com.jeta.forms.gui.components.EmptyComponentFactory;
034: import com.jeta.forms.gui.form.FormComponent;
035: import com.jeta.forms.gui.form.GridCellEvent;
036: import com.jeta.forms.gui.form.GridComponent;
037: import com.jeta.forms.gui.form.GridOverlay;
038: import com.jeta.forms.gui.form.GridView;
039: import com.jeta.forms.gui.form.GridViewEvent;
040: import com.jeta.forms.gui.form.GridViewListener;
041: import com.jeta.forms.gui.form.ReadOnlyConstraints;
042: import com.jeta.forms.gui.form.StandardComponent;
043: import com.jeta.forms.gui.formmgr.FormManager;
044: import com.jeta.forms.project.ProjectManager;
045: import com.jeta.forms.store.memento.ComponentMemento;
046: import com.jeta.forms.store.memento.FormMemento;
047: import com.jeta.open.registry.JETARegistry;
048: import com.jeta.open.resources.AppResourceLoader;
049:
050: /**
051: */
052: public class DesignFormComponent extends FormComponent implements
053: GridViewListener {
054: /**
055: * The panel at the top of this component that contains the expand/hide and
056: * edit buttons for this form. These buttons are only visible in design
057: * mode.
058: */
059: private JPanel m_btnpanel;
060: private AbstractButton m_expand_btn;
061: private AbstractButton m_edit_btn;
062: private AbstractButton m_grid_btn;
063:
064: /**
065: * Creates a <code>DesignFormComponent</code> instance.
066: */
067: public DesignFormComponent() {
068:
069: }
070:
071: /**
072: * Creates a <code>DesignFormComponent</code> instance with the specified
073: * id, child bean, and parent view.
074: *
075: * @param id
076: * the unique id for this form.
077: * @param jbean
078: * the underlying GridView
079: * @param parentView
080: * the parent for this form.
081: * @param embedded
082: * flag that indicates if this form is embedded
083: */
084: public DesignFormComponent(String id, JETABean jbean,
085: GridView parentView, boolean embedded) throws FormException {
086: super (id, jbean, parentView, embedded);
087: }
088:
089: /**
090: * Creates the control buttons at the top of the form. The control buttons
091: * are only visible in the designer.
092: *
093: * @return the panel that contains the control buttons for the form.
094: */
095: private JPanel createControlsPanel() {
096: // expand/hide buttons for child form when in design mode.
097: m_btnpanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
098: m_btnpanel.setOpaque(false);
099: m_btnpanel.setFocusable(false);
100:
101: JButton btn = new JButton(
102: AppResourceLoader
103: .getImage("jeta.resources/images/forms/form_control_collapse.gif"));
104: Dimension d = new Dimension(12, 20);
105: btn.setPreferredSize(d);
106: btn.setMinimumSize(d);
107: btn.setBorderPainted(false);
108: btn.setFocusPainted(false);
109: btn.setContentAreaFilled(false);
110: btn.setFocusable(false);
111:
112: m_expand_btn = btn;
113: m_btnpanel.add(btn);
114:
115: m_btnpanel.add(javax.swing.Box.createHorizontalStrut(2));
116: btn = new JButton(
117: AppResourceLoader
118: .getImage("jeta.resources/images/forms/form_control_edit.gif"));
119: btn.setPreferredSize(d);
120: btn.setMinimumSize(d);
121: btn.setBorderPainted(false);
122: btn.setFocusPainted(false);
123: btn.setContentAreaFilled(false);
124: btn.setFocusable(false);
125:
126: m_edit_btn = btn;
127: m_btnpanel.add(btn);
128:
129: m_btnpanel.add(javax.swing.Box.createHorizontalStrut(2));
130: btn = new JButton(
131: AppResourceLoader
132: .getImage("jeta.resources/images/forms/form_control_grid.gif"));
133: btn.setPreferredSize(d);
134: btn.setMinimumSize(d);
135: btn.setBorderPainted(false);
136: btn.setFocusPainted(false);
137: btn.setFocusable(false);
138:
139: btn.setContentAreaFilled(false);
140: m_grid_btn = btn;
141: m_btnpanel.add(btn);
142:
143: return m_btnpanel;
144: }
145:
146: /**
147: * The panel at the top of this component that contains the expand/hide and
148: * edit buttons for this form. These buttons are only visible during design
149: * mode.
150: *
151: * @return the panel that contains the control buttons for the form.
152: */
153: public JPanel getButtonPanel() {
154: return m_btnpanel;
155: }
156:
157: /**
158: * Returns the component that renders the grid lines for the GridView
159: * associated with this form.
160: *
161: * @return the GridOverlay component associated with the GridView that is
162: * contained within this component.
163: */
164: public GridOverlay getChildOverlay() {
165: GridView gv = getChildView();
166: return gv.getOverlay();
167: }
168:
169: /**
170: * Returns the control button used to open a nested form in the editor. This
171: * button is only visible in design mode.
172: *
173: * @return the button used to open a nested form in the editor
174: */
175: public AbstractButton getEditButton() {
176: return m_edit_btn;
177: }
178:
179: /**
180: * Returns the control button used to expand/hide a nested form in the
181: * editor. This button is only visible in design mode.
182: *
183: * @return the button used to expand/hide a nested form
184: */
185: public AbstractButton getExpandButton() {
186: return m_expand_btn;
187: }
188:
189: /**
190: * Returns the control button used to show/hide the grid lines of a form in
191: * the editor. This button is only visible in design mode.
192: *
193: * @return the button used to show/hide the grid lines
194: */
195: public AbstractButton getGridButton() {
196: return m_grid_btn;
197: }
198:
199: /**
200: * We keep this event around so we don't have to instantiate every time a
201: * cell is selected.
202: */
203: private GridCellEvent m_cell_changed = new GridCellEvent(
204: GridCellEvent.CELL_CHANGED, this );
205:
206: /**
207: * GridViewListener implementation. This method is called when events are
208: * fired from the child GridView contained by this FormComponent. All events
209: * are forwarded up the listener chain.
210: *
211: * @param evt
212: * the event fired by the GridView contained by this form.
213: */
214: public void gridChanged(GridViewEvent evt) {
215: if (evt.getComponentEvent() != null)
216: fireGridCellEvent(evt.getComponentEvent());
217: else {
218: fireGridCellEvent(m_cell_changed);
219: }
220: }
221:
222: /**
223: * Returns the flag that indicates if the grid view associated with this
224: * form is visible. This is different than showing the grid lines. This call
225: * determines if the underlying components in the view in addition to the
226: * grid lines are visible.
227: */
228: public boolean isGridViewVisible() {
229: GridView view = getChildView();
230: DesignGridOverlay overlay = (DesignGridOverlay) view
231: .getOverlay();
232: return !overlay.isOpaque();
233: }
234:
235: /**
236: * Creates and initializes a FormComponent from the given form memento.
237: */
238: protected FormComponent openLinkedForm(FormMemento fm)
239: throws FormException {
240: FormManager fmgr = (FormManager) JETARegistry
241: .lookup(FormManager.COMPONENT_ID);
242:
243: /**
244: * If we are in design mode and a child form is encountered that is
245: * linked, then we open the form using the formmanager. This is because
246: * another view might have the linked form opened already. This can
247: * never happen if the form is embedded.
248: */
249: if (FormUtils.isDesignMode()) {
250: /**
251: * Here we must assume that any other views to the same form *must*
252: * be deactivated by the FormManager.
253: */
254: FormComponent fc = fmgr.getForm(fm.getId());
255: if (fc == null) {
256:
257: ProjectManager pmgr = (ProjectManager) JETARegistry
258: .lookup(ProjectManager.COMPONENT_ID);
259: String abspath = pmgr.getAbsolutePath(fm
260: .getRelativePath());
261: fc = fmgr.openLinkedForm(abspath);
262: }
263: return fc;
264: } else {
265: FormUtils.safeAssert(false);
266: return super .openLinkedForm(fm);
267: }
268: }
269:
270: /**
271: * Shows/hides the control buttons at the top of this component
272: */
273: public void setControlButtonsVisible(boolean bvis) {
274: if (m_btnpanel != null) {
275: remove(m_btnpanel);
276: if (bvis) {
277: add(m_btnpanel, BorderLayout.NORTH);
278: }
279: }
280: }
281:
282: /**
283: * Shows or hides the grid view associated with this form. This is different
284: * than showing the grid lines. This call also shows/hides the underlying
285: * components in the view in addition to the grid lines.
286: */
287: public void setGridViewVisible(boolean bvis) {
288: GridView view = getChildView();
289: DesignGridOverlay overlay = (DesignGridOverlay) view
290: .getOverlay();
291: overlay.setOpaque(!bvis);
292: overlay.setGridVisible(bvis);
293: if (bvis) {
294: m_expand_btn
295: .setIcon(AppResourceLoader
296: .getImage("jeta.resources/images/forms/form_control_collapse.gif"));
297: } else {
298: m_expand_btn
299: .setIcon(AppResourceLoader
300: .getImage("jeta.resources/images/forms/form_control_expand.gif"));
301: }
302: }
303:
304: /**
305: * Override GridComponent implementation so we can add the child to this
306: * container for the design view.
307: */
308: protected void setBean(JETABean jbean) {
309: super .setBean(jbean);
310:
311: FormUtils.safeAssert(jbean.getDelegate() instanceof GridView);
312: ((GridView) jbean.getDelegate()).addListener(this );
313:
314: if (FormUtils.isDesignMode()) {
315: add(javax.swing.Box.createVerticalStrut(2),
316: BorderLayout.SOUTH);
317: if (m_btnpanel == null)
318: add(createControlsPanel(), BorderLayout.NORTH);
319:
320: setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 2,
321: 2, 2));
322: } else {
323: assert (false);
324: }
325: }
326:
327: /**
328: * Performs any final initialization of this form component after it's state
329: * has been restored. The main operation is to add empty components where
330: * needed. When in design mode, every cell in the grid has a GridComponent.
331: * The reason is because we need to enforce a minimum size for the cell when
332: * the user sets the row/col size to preferred. If not, the cell size would
333: * be zero if nothing were there. However, in run mode, we don't want to
334: * create an empty component for every single cell. For example, a 20x20
335: * grid would require 400 components. To prevent this, we only add 1 empty
336: * component per row and column. This allows the runtime form to look
337: * approximately like the design time forms with rows/cols that have no
338: * components. We use the grid_cache to keep track of which columns and rows
339: * have had empty components added.
340: */
341: protected void postSetState(ComponentMemento cm) {
342: try {
343: GridView view = getChildView();
344: ComponentSource compsrc = (ComponentSource) JETARegistry
345: .lookup(ComponentSource.COMPONENT_ID);
346: EmptyComponentFactory factory = new EmptyComponentFactory(
347: compsrc);
348: for (int col = 1; col <= view.getColumnCount(); col++) {
349: for (int row = 1; row <= view.getRowCount(); row++) {
350: GridComponent gc = view.getGridComponent(col, row);
351: if (gc == null) {
352: gc = (StandardComponent) factory
353: .createComponent("empty", view);
354: view.addComponent(gc, new ReadOnlyConstraints(
355: col, row));
356: }
357: }
358: }
359: } catch (Exception e) {
360: e.printStackTrace();
361: }
362: }
363:
364: /**
365: * Resets this component from a previously saved state.
366: *
367: * @param memento
368: */
369: public void setState(ComponentMemento memento) throws FormException {
370: super .setState(memento);
371: // **** now make sure that any empty cells are properly filled
372: getChildView().enableEvents(true);
373: }
374: }
|