001 /* sillyview : a free model-view-controller system for Java
002 * Copyright (C) 2004 T.J. Willis
003 *
004 * This program is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU General Public License
006 * as published by the Free Software Foundation; either version 2
007 * of the License, or (at your option) any later version.
008 *
009 * This program 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
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program; if not, write to the Free Software
016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
017 *
018 * $Header: /cvsroot/sillyview/sillyview/src/net/sourceforge/sillyview/JPanelView.java,v 1.2 2004/05/15 01:58:51 tj_willis Exp $
019 */
020 package net.sourceforge.sillyview;
021
022 import javax.swing.*;
023 import javax.swing.event.HyperlinkListener;
024 import javax.swing.border.*;
025 import java.util.Map;
026 import java.util.Set;
027 import org.apache.log4j.*;
028
029 /**
030 * This is a central class in sillyview. It displays a given WidgetModel
031 * as a JLabel, a JEditorPane, or a HTMLPane. For implementation reasons
032 * it extends javax.swing.Box, instead of javax.swing.JPanel.
033 *
034 * @author <a href="mailto:tj_willis@users.sourceforge.net">T.J. Willis</a>
035 * @has 0..1 Has - net.sourceforge.sillyview.HTMLPane
036 * @has 0..1 Has - javax.swing.JEditorPane
037 * @has 0..1 Has - javax.swing.JLabel
038 * @version 1.0
039 */
040 public class JPanelView
041 extends javax.swing.Box
042 implements WidgetView
043 {
044 private static final int MIN = 0;
045 private static final int PREF = 1;
046 private Category cat
047 = Category.getInstance(JPanelView.class.getName());
048 /**
049 * This panel's title.
050 *
051 */
052 protected String title;
053
054 /**
055 * If data displayed as a JLabel, this is that JLabel.
056 *
057 */
058 protected JLabel lab;
059 /**
060 * If data displayed in a JEditorPane, this is that JEditorPane.
061 *
062 */
063 protected JEditorPane ed;
064 /**
065 * The component that the data is displayed in.
066 *
067 */
068 protected Object comp;
069
070 /**
071 * The model this view gets its data from.
072 *
073 */
074 protected WidgetModel mod;
075 /**
076 * A token for setting the view's text.
077 *
078 */
079 public static final String TEXT = "<@TEXT>";
080 /**
081 * A token for setting the view's hyperlink listener.
082 *
083 */
084 public static final String HYPERLINK_LISTENER = "<@_HYPERLINK_LISTENER>";
085
086 /**
087 * If you want data displayed in a JLabel.
088 */
089 public static final int JLABEL = 0;
090 /**
091 * If you want data displayed in a JEditorPane.
092 */
093 public static final int JEDITORPANE = 1;
094 /**
095 * If you want data displayed in a HTMLPane.
096 */
097 public static final int HTMLPANE = 2;
098
099 /**
100 * Creates a new <code>JPanelView</code> instance backed by the
101 * given WidgetModel and of type JLABEL, JEDITORPANE, or HTMLPANE.
102 *
103 * @param model a <code>WidgetModel</code> value
104 * @param componentType an <code>int</code> value
105 */
106 public JPanelView (final WidgetModel model, final int componentType) {
107 super (BoxLayout.Y_AXIS);
108 //java.awt.BorderLayout b = new java.awt.BorderLayout();
109 //setLayout(b);
110 setDoubleBuffered(true);
111 mod = model;
112
113 if (componentType == JLABEL) {
114 lab = new JLabel ((String) (model.getCurrentModel ()));
115 comp = lab;
116 add (lab);
117 } else if (componentType == JEDITORPANE) {
118 ed = new JEditorPane ("text/html", null);
119 ed.setText ((String) (model.getCurrentModel ()));
120 ed.setEditable (false);
121 comp = ed;
122 add (ed); //scroller);
123 } else if (componentType == HTMLPANE) {
124 String x = ((String) (model.getCurrentModel ()));
125 ed = new HTMLPane (x);
126 comp = ed;
127 add (ed);
128 }
129 }
130
131 /**
132 * Sets this views text.
133 *
134 * @param txt a <code>String</code> value
135 */
136 protected void setText (final String txt) {
137 if (comp == lab) {
138 lab.setText (txt);
139 } else if (comp == ed) {
140 ed.setText (txt);
141 }
142 }
143
144 /**
145 * Gets this view's text.
146 *
147 * @return a <code>String</code> value
148 */
149 public String getText () {
150 if (comp == ed)
151 return ed.getText ();
152 if (comp == lab)
153 return lab.getText ();
154 return null;
155 }
156
157 /**
158 * Adds all the name/value pairs and then updates the model. If
159 * the named token already exists, replace the value. This is more
160 * efficient than many calls to setToken(), because model.getCurrentModel
161 * is only called once.
162 *
163 */
164 public final void addTokens (final Map < Object, Object > props) {
165 if (props == null) {
166 return; // FIXME: clear all tokens in model
167 }
168 Set keys = props.keySet ();
169 for (Object k:keys) {
170 String key = k.toString ();
171 mod.setToken (key, props.get (key));
172 }
173 setText (mod.getCurrentModel ().toString ());
174
175 }
176
177 /**
178 * Sets the named token to the given value and then recalculates my
179 * text. Most tokens, other than TITLE and HYPERLINK_LISTENER will
180 * be passed on to the model for handling.
181 *
182 * @param key an <code>Object</code> value
183 * @param value an <code>Object</code> value
184 */
185 public final void setToken (final Object key, Object value) {
186 if (key == null)
187 return;
188
189 String ti = "";
190 if (value != null)
191 ti = value.toString ();
192
193 String la = key.toString ();
194 if (TITLE.equals (la)) {
195 title = ti;
196 setTitle (ti);
197 } else if (HYPERLINK_LISTENER.equals (la)) {
198 if (comp == lab) {
199 //throw new NotSupportedException(001);
200 } else if (comp == ed) {
201 ed.addHyperlinkListener ((HyperlinkListener) value);
202 }
203 return;
204 }
205 mod.setToken (key, value);
206 setText (mod.getCurrentModel ().toString ());
207 }
208
209 /**
210 * Gets the named value. Most values will come from the backing
211 * model.
212 *
213 * @param key an <code>Object</code> value
214 * @return an <code>Object</code> value
215 */
216 public final Object getValue (final Object key) {
217 if (key == null)
218 return null;
219 String la = key.toString ();
220 if (TITLE.equals (la))
221 return title;
222
223 return mod.getValue (key);
224 }
225
226 /**
227 * Sets the panel's title to the given text, providing a titled border.
228 *
229 * @param val a <code>String</code> value
230 */
231 protected final void setTitle (final String val) {
232 title = val;
233 Border etched = BorderFactory.createEtchedBorder ();
234 etched = BorderFactory.createTitledBorder (etched, val);
235 setBorder (etched);
236 }
237
238 /**
239 * Returns the backing model.
240 *
241 * @return a <code>WidgetModel</code> value
242 */
243 public final WidgetModel getModel () {
244 return mod;
245 }
246
247 /**
248 * Sets the backing model.
249 *
250 * @param newModel a <code>WidgetModel</code> value
251 */
252 public final void setModel (final WidgetModel newModel) {
253 mod = newModel;
254 }
255
256 /**
257 * Sets the preferred size of this panel as well as the view component.
258 *
259 * @param size a <code>java.awt.Dimension</code> value
260 */
261 public void setPreferredSize (java.awt.Dimension size) {
262 super.setPreferredSize (size);
263 resizeComponent(PREF,size);
264 }
265
266
267 private void resizeComponent(int which, java.awt.Dimension size){
268 try {
269 if (comp == null || !(comp instanceof JComponent))
270 return;
271 JComponent c = (JComponent) comp;
272 if(which==PREF)
273 c.setPreferredSize (size);
274 else
275 c.setMinimumSize( size);
276 validate ();
277 } catch (Exception ex) {
278 cat.warn("resize exception : ",ex);
279 }
280
281 }
282
283
284 /**
285 * Sets the minimum size of this panel as well as the view component.
286 *
287 * @param size a <code>java.awt.Dimension</code> value
288 */
289 public void setMinimumSize (java.awt.Dimension size) {
290 super.setMinimumSize (size);
291 resizeComponent(MIN,size);
292 }
293
294 /**
295 * If the view component is a HTMLPane, will set its autodump property.
296 *
297 * @param b a <code>boolean</code> value
298 */
299 public void setAutoDump(boolean b){
300 if(ed!=null && ed instanceof HTMLPane){
301 HTMLPane h = (HTMLPane) ed;
302 h.setAutoDump(b);
303 }
304
305 }
306 }