QedeqTreeCellRenderer.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2013,  Michael Meyling <mime@qedeq.org>.
004  *
005  * "Hilbert II" is free software; you can redistribute
006  * it and/or modify it under the terms of the GNU General Public
007  * License as published by the Free Software Foundation; either
008  * version 2 of the License, or (at your option) any later version.
009  *
010  * This program is distributed in the hope that it will be useful,
011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013  * GNU General Public License for more details.
014  */
015 
016 package org.qedeq.gui.se.tree;
017 
018 import java.awt.Component;
019 import java.awt.Graphics;
020 
021 import javax.swing.Icon;
022 import javax.swing.ImageIcon;
023 import javax.swing.JTree;
024 import javax.swing.tree.DefaultMutableTreeNode;
025 import javax.swing.tree.DefaultTreeCellRenderer;
026 
027 import org.qedeq.base.trace.Trace;
028 import org.qedeq.gui.se.util.DecoratedIcon;
029 import org.qedeq.gui.se.util.GuiHelper;
030 import org.qedeq.kernel.bo.common.QedeqBo;
031 import org.qedeq.kernel.se.common.Plugin;
032 import org.qedeq.kernel.se.state.AbstractState;
033 import org.qedeq.kernel.se.state.DependencyState;
034 import org.qedeq.kernel.se.state.FormallyProvedState;
035 import org.qedeq.kernel.se.state.LoadingImportsState;
036 import org.qedeq.kernel.se.state.LoadingState;
037 import org.qedeq.kernel.se.state.WellFormedState;
038 
039 import furbelow.AnimatedIcon;
040 
041 /**
042  * Renderer for a JTree.
043  *
044  @author  Michael Meyling
045  */
046 public final class QedeqTreeCellRenderer extends DefaultTreeCellRenderer {
047 
048     /** This class. */
049     private static final Class CLASS = QedeqTreeCellRenderer.class;
050 
051     /** Status icon. */
052     private static ImageIcon startIcon
053         = createImageIcon("module_start.gif");
054 
055     /** Status icon. */
056     private static ImageIcon loadedIcon
057         = createImageIcon("module_loaded.gif");
058 
059     /** Status icon. */
060     private static ImageIcon loadedImportsIcon
061         = createImageIcon("module_loaded_required.gif");    // LATER 20130318 m31: other icon?
062 
063     /** Status icon. */
064     private static ImageIcon loadedRequiredIcon
065         = createImageIcon("module_loaded_required.gif");
066 
067     /** Status icon. */
068     private static ImageIcon wellFormedIcon
069         = createImageIcon("module_checked.gif");
070 
071     /** Status icon. */
072     private static ImageIcon formallyProvedIcon
073         = createImageIcon("module_checked2.gif");
074 
075     /** Status icon. */
076     private static AnimatedIcon startNextIcon
077         new AnimatedIcon(createImageIcon("next_module_start.gif"));
078 
079     /** Status icon. */
080     private static AnimatedIcon startFlashIcon
081         new AnimatedIcon(createImageIcon("flash_module_start.gif"));
082 
083     /** Status icon. */
084     private static AnimatedIcon loadedNextIcon
085         new AnimatedIcon(createImageIcon("next_module_loaded.gif"));
086 
087     /** Status icon. */
088     private static AnimatedIcon loadedFlashIcon
089         new AnimatedIcon(createImageIcon("flash_module_loaded.gif"));
090 
091     /** Status icon. */
092     private static AnimatedIcon loadedImportsNextIcon       // LATER 20130318 m31: other icon?
093         new AnimatedIcon(createImageIcon("next_module_loaded_required.gif"));
094 
095     /** Status icon. */
096     private static AnimatedIcon loadedImportsFlashIcon     // LATER 20130318 m31: other icon?
097         new AnimatedIcon(createImageIcon("flash_module_loaded_required.gif"));
098 
099     /** Status icon. */
100     private static AnimatedIcon loadedRequiredNextIcon
101         new AnimatedIcon(createImageIcon("next_module_loaded_required.gif"));
102 
103     /** Status icon. */
104     private static AnimatedIcon loadedRequiredFlashIcon
105         new AnimatedIcon(createImageIcon("flash_module_loaded_required.gif"));
106 
107     /** Status icon. */
108     private static AnimatedIcon wellFormedNextIcon
109         new AnimatedIcon(createImageIcon("next_module_checked.gif"));
110 
111     /** Status icon. */
112     private static AnimatedIcon wellFormedFlashIcon
113         new AnimatedIcon(createImageIcon("flash_module_checked.gif"));
114 
115     /** Status icon. */
116     private static AnimatedIcon formallyProvedFlashIcon
117         new AnimatedIcon(createImageIcon("flash_module_checked2.gif"));
118 
119     /** Status icon. */
120     private static ImageIcon basicErrorOverlayIcon
121         = GuiHelper.readImageIcon("eclipse/error_co_dl.gif");
122 
123     /** Status icon. */
124     private static ImageIcon pluginErrorOverlayIcon
125         = GuiHelper.readImageIcon("eclipse/error_co_ur.gif");
126 
127     /** Status icon. */
128     private static ImageIcon pluginWarningOverlayIcon
129         = GuiHelper.readImageIcon("eclipse/warning_co_ur.gif");
130 
131     static ImageIcon createImageIcon(final String name) {
132         return GuiHelper.readImageIcon("qedeq/16x16/" + name);
133 
134     }
135 
136 // LATER mime 20080502: do we want to leave it for our alternative "paint" or do we delete it?
137 //
138 //    /** Color to use for the foreground for selected nodes. */
139 //    private Color textSelectionColor = UIManager.getColor("Tree.selectionForeground");
140 //
141 //    /** Color to use for the foreground for non-selected nodes. */
142 //    private Color textNonSelectionColor = UIManager.getColor("Tree.textForeground");
143 //
144 //    /** Color to use for the background when a node is selected. */
145 //    private Color backgroundSelectionColor = UIManager.getColor("Tree.selectionBackground");
146 //
147 //    /** Color to use for the background when the node isn't selected. */
148 //    private Color backgroundNonSelectionColor = UIManager.getColor("Tree.textBackground");
149 
150     public QedeqTreeCellRenderer() {
151         super();
152     }
153 
154     public synchronized Component getTreeCellRendererComponent(final JTree tree,
155             final Object value, final boolean isSelected,
156             final boolean expanded, final boolean leaf, final int row,
157             final boolean hasFocus) {
158 
159         final String method = "getTreeCellRendererComponent";
160         Trace.param(CLASS, this, method, row + " is selected", isSelected);
161         Trace.param(CLASS, this, method, row + " is expanded", expanded);
162         Trace.param(CLASS, this, method, row + " hasFocus", hasFocus);
163         Trace.param(CLASS, this, method, row + " leaf", leaf);
164         Trace.param(CLASS, this, method, row + " maxSelectionRow", tree.getMaxSelectionRow());
165         Trace.param(CLASS, this, method, row + " selectionCount", tree.getSelectionCount());
166         Trace.param(CLASS, this, method, row + " rowCount", tree.getRowCount());
167         Trace.param(CLASS, this, method, row + " tree path", tree.getPathForRow(row));
168 
169         ModuleElement unit;
170         QedeqBo prop;
171 /* m31 20080502: Debugging code
172         TreeModel model = tree.getModel();
173         BasicTreeUI ui = (BasicTreeUI) tree.getUI();
174         VariableHeightLayoutCache vhlc = null;
175         Vector visibleNodes = null;
176         try {
177             vhlc = (VariableHeightLayoutCache) IoUtility.getFieldContentSuper(ui, "treeState");
178             visibleNodes = (Vector) IoUtility.getFieldContentSuper(vhlc, "visibleNodes");
179             System.out.println("vectorSize = " + visibleNodes.size());
180             for (int i = 0; i < visibleNodes.size(); i++) {
181                 System.out.println("  " + visibleNodes.get(i));
182             }
183         } catch (Throwable e) {
184             e.printStackTrace();
185         }
186 */
187         super.getTreeCellRendererComponent(tree, value, isSelected, expanded,
188             leaf, row, hasFocus);
189         if (value instanceof DefaultMutableTreeNode) {
190             if (((DefaultMutableTreeNodevalue).getUserObject()
191                     instanceof ModuleElement) {
192                 unit = (ModuleElement) ((DefaultMutableTreeNodevalue).getUserObject();
193                 setText(unit.getName());
194             else {
195                 prop = (QedeqBo) ((DefaultMutableTreeNodevalue).getUserObject();
196                 final String text = prop.getName();
197                 setText(text);
198                 final AbstractState currentState = prop.getCurrentState();
199                 final Plugin plugin = prop.getCurrentlyRunningPlugin();
200                 if (prop.isLoaded()) {
201                     setToolTipText(prop.getUrl().toString());
202                 else {
203                     setToolTipText(GuiHelper.getToolTipText(prop.getStateDescription()));
204                 }
205 //                setIcon(null);
206 //                System.out.println(prop.getStateDescription());
207 //                System.out.println("current state=" + currentState + " " + currentState.getClass());
208 //                System.out.println("lasz suc.stat=" + succesfullState + " " + succesfullState.getClass());
209 //                System.out.println();
210                 if (currentState == LoadingState.STATE_DELETED) {
211                     setIcon(null);
212                 else if (currentState == LoadingState.STATE_UNDEFINED) {
213                     if (plugin == null) {
214                         setIcon(prop, startIcon);
215                     else {
216                         setIcon(startFlashIcon);
217                     }
218                 else if (currentState == LoadingState.STATE_LOADED) {
219                     if (plugin == null) {
220                         setIcon(prop, loadedIcon);
221                     else {
222                         setIcon(loadedFlashIcon);
223                     }
224                 else if (currentState instanceof LoadingState) {
225                     if (currentState.isFailure()) {
226                         if (plugin == null) {
227                             setIcon(prop, startIcon);
228                         else {
229                             setIcon(startFlashIcon);
230                         }
231                     else {
232                         setIcon(startNextIcon);
233                     }
234                 else if (currentState == LoadingImportsState.STATE_LOADED_IMPORTED_MODULES) {
235                     if (plugin == null) {
236                         setIcon(prop, loadedImportsIcon);
237                     else {
238                         setIcon(loadedImportsFlashIcon);
239                     }
240                 else if (currentState instanceof LoadingImportsState) {
241                     if (currentState.isFailure()) {
242                         if (plugin == null) {
243                             setIcon(prop, loadedImportsIcon);
244                         else {
245                             setIcon(loadedImportsFlashIcon);
246                         }
247                     else {
248                         setIcon(loadedImportsNextIcon);
249                     }
250                 else if (currentState == DependencyState.STATE_LOADED_REQUIRED_MODULES) {
251                     if (plugin == null) {
252                         setIcon(prop, loadedRequiredIcon);
253                     else {
254                         setIcon(loadedRequiredFlashIcon);
255                     }
256                 else if (currentState instanceof DependencyState) {
257                     if (currentState.isFailure()) {
258                         if (plugin == null) {
259                             setIcon(prop, loadedIcon);
260                         else {
261                             setIcon(loadedFlashIcon);
262                         }
263                     else {
264                         setIcon(loadedNextIcon);
265                     }
266                 else if (currentState == WellFormedState.STATE_CHECKED) {
267                     if (plugin == null) {
268                         setIcon(prop, wellFormedIcon);
269                     else {
270                         setIcon(wellFormedFlashIcon);
271                     }
272                 else if (currentState instanceof WellFormedState) {
273                     if (currentState.isFailure()) {
274                         if (plugin == null) {
275                             setIcon(prop, loadedRequiredIcon);
276                         else {
277                             setIcon(loadedRequiredFlashIcon);
278                         }
279                     else {
280                         setIcon(loadedRequiredNextIcon);
281                     }
282                 else if (currentState == FormallyProvedState.STATE_CHECKED) {
283                     if (plugin == null) {
284                         setIcon(prop, formallyProvedIcon);
285                     else {
286                         setIcon(formallyProvedFlashIcon);
287                     }
288                 else if (currentState instanceof FormallyProvedState) {
289                     if (currentState.isFailure()) {
290                         if (plugin == null) {
291                             setIcon(prop, wellFormedIcon);
292                         else {
293                             setIcon(wellFormedFlashIcon);
294                         }
295                     else {
296                         setIcon(wellFormedNextIcon);
297                     }
298                 else {    // unknown loading state
299                     throw new IllegalStateException("unknown module state: "
300                         + currentState.getText());
301                 }
302 
303             }
304         }
305     // LATER m31 20080502: do we want to leave it for our alternative "paint" or do we delete it?
306 /*
307         if (isSelected) {
308             setBackground(backgroundSelectionColor);
309             setForeground(textSelectionColor);
310         } else {
311             setBackground(backgroundNonSelectionColor);
312             setForeground(textNonSelectionColor);
313         }
314 */
315 // mime 20080430: comment out, debug code!
316 //        Trace.trace(CLASS, this, method, "-- global info");
317 //        final DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
318 //        Trace.param(CLASS, this, method, "-- child", node.getChildCount());
319 //        for (int i = 0; i < node.getChildCount(); i++) {
320 //            Trace.param(CLASS, this, method, "--- node" + i,  node.getChildAt(i));
321 //            Trace.param(CLASS, this, method, "--- child count" + i,
322 //                node.getChildAt(i).getChildCount());
323 //        }
324 
325         return this;
326     }
327 
328     // LATER m31 20080502: do we want to rename it back to "paint" or do we delete it?
329     /*
330      * paint is subclassed to draw the background correctly.  JLabel
331      * currently does not allow backgrounds other than white, and it
332      * will also fill behind the icon. Something that isn't desirable.
333      */
334    public void paintttttt(final Graphics g) {
335        final String method = "paint";
336        Trace.param(CLASS, this, method, "label", getText());
337        Icon currentI = getIcon();
338        if (currentI != null && getText() != null) {
339            int offset = (currentI.getIconWidth() + getIconTextGap());
340            g.setColor(getBackground());
341            if (getComponentOrientation().isLeftToRight()) {
342                 g.fillRect(offset, 0, getWidth() - offset, getHeight() 1);
343            else {
344                 g.fillRect(00, getWidth() - offset, getHeight() 1);
345            }
346        else {
347            g.fillRect(00, getWidth() 1, getHeight() 1);
348        }
349        super.paint(g);
350     }
351 
352     private void setIcon(final QedeqBo qedeq, final ImageIcon icon) {
353         final DecoratedIcon ic = new DecoratedIcon(icon);
354         if (qedeq.hasBasicFailures()) {
355             ic.decorate(basicErrorOverlayIcon);
356         }
357 // FIXME 20130220 m31: we have to separate basic failures from plugin errors, here a method is missing
358 //        if (qedeq.hasErrors()) {
359 //            ic.decorate(pluginErrorOverlayIcon);
360 //        }
361         if (qedeq.hasWarnings()) {
362             ic.decorate(pluginWarningOverlayIcon);
363         }
364         setIcon(ic);
365     }
366 
367 
368 }