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 }