~ubuntu-branches/ubuntu/wily/weka/wily

« back to all changes in this revision

Viewing changes to src/main/java/weka/gui/ensembleLibraryEditor/tree/PropertyNode.java

  • Committer: Bazaar Package Importer
  • Author(s): tony mancill
  • Date: 2011-08-05 22:40:50 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110805224050-a01vkwst9epdi4sw
Tags: 3.6.5-1
* Team upload.
* New upstream version (Closes: #632082, #598400)
* Bump Standards-Version to 3.9.2 (no changes required).
* Freshen jar.patch; remove java_cup.patch (incorporated upstream)
* Add README.source to document process of obtaining .png resources.
* Add myself to Uploaders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *    This program is free software; you can redistribute it and/or modify
3
 
 *    it under the terms of the GNU General Public License as published by
4
 
 *    the Free Software Foundation; either version 2 of the License, or
5
 
 *    (at your option) any later version.
6
 
 *
7
 
 *    This program is distributed in the hope that it will be useful,
8
 
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
 *    GNU General Public License for more details.
11
 
 *
12
 
 *    You should have received a copy of the GNU General Public License
13
 
 *    along with this program; if not, write to the Free Software
14
 
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15
 
 */
16
 
 
17
 
/*
18
 
 *    PropertyNode.java
19
 
 *    Copyright (C) 2006 Robert Jung
20
 
 *
21
 
 */
22
 
 
23
 
package weka.gui.ensembleLibraryEditor.tree;
24
 
 
25
 
import weka.gui.GenericObjectEditor;
26
 
import weka.gui.ensembleLibraryEditor.AddModelsPanel;
27
 
 
28
 
import java.beans.PropertyEditor;
29
 
import java.util.Vector;
30
 
 
31
 
import javax.swing.JOptionPane;
32
 
import javax.swing.JRootPane;
33
 
import javax.swing.JTree;
34
 
import javax.swing.tree.DefaultMutableTreeNode;
35
 
import javax.swing.tree.DefaultTreeModel;
36
 
 
37
 
/**
38
 
 * This node class represents individual parameters of generic objects
39
 
 * (in practice this means classifiers).  So all direct children of a
40
 
 * classifier or other generic objects in the tree are going to be 
41
 
 * property nodes.  Note that these nodes do not themselves have editors
42
 
 * all editing in the user interface actaully happens in the child
43
 
 * nodes of this class that it controls.  On top of creating these 
44
 
 * child nodes and initializing them with the correct editing 
45
 
 * configuration, this class is also responsible for obtaining all of 
46
 
 * the possible values from the child nodes.
47
 
 *  
48
 
 * @author  Robert Jung (mrbobjung@gmail.com)
49
 
 * @version $Revision: 1.1 $
50
 
 */
51
 
public class PropertyNode 
52
 
  extends DefaultMutableTreeNode {
53
 
  
54
 
  /** for serialization */
55
 
  private static final long serialVersionUID = 8179038568780212829L;
56
 
 
57
 
  /** this is a reference to the parent panel of the JTree which is
58
 
   * needed to display correctly anchored JDialogs*/
59
 
  private final AddModelsPanel m_ParentPanel;
60
 
  
61
 
  /** the name of the node to be displayed */
62
 
  private String m_Name;
63
 
  
64
 
  /** the node's tip text*/
65
 
  private String m_ToolTipText;
66
 
  
67
 
  /** The propertyEditor created for the node, this is very useful in
68
 
   * figuring out exactly waht kind of child editor nodes to create */
69
 
  private PropertyEditor m_PropertyEditor;
70
 
  
71
 
  /** a reference to the tree model is necessary to be able to add and 
72
 
   * remove nodes in the tree */
73
 
  private DefaultTreeModel m_TreeModel;
74
 
  
75
 
  /** a reference to the tree */
76
 
  private JTree m_Tree;
77
 
  
78
 
  /**
79
 
   * The constructor initialiazes the member variables of this node, 
80
 
   * Note that the "value" of this generic object is stored as the treeNode
81
 
   * user object. After the values are initialized the constructor calls
82
 
   * the addEditorNodes to create all the child nodes necessary to allow
83
 
   * users to specify ranges of parameter values meaningful for the 
84
 
   * parameter that this node represents.
85
 
   * 
86
 
   * @param tree                the tree to use
87
 
   * @param panel               the pabel
88
 
   * @param name                the name
89
 
   * @param toolTipText         the tooltip
90
 
   * @param value               the actual value
91
 
   * @param pe                  the property editor
92
 
   */
93
 
  public PropertyNode(JTree tree, AddModelsPanel panel, String name,
94
 
      String toolTipText, Object value, PropertyEditor pe) {
95
 
    
96
 
    super(value);
97
 
    
98
 
    m_Tree = tree;
99
 
    m_TreeModel = (DefaultTreeModel) m_Tree.getModel();
100
 
    m_ParentPanel = panel;
101
 
    m_Name = name;
102
 
    m_ToolTipText = toolTipText;
103
 
    m_PropertyEditor = pe;
104
 
    
105
 
    addEditorNodes(name, toolTipText);
106
 
  }
107
 
  
108
 
  /**
109
 
   * getter for the tooltip text
110
 
   * 
111
 
   * @return tooltip text
112
 
   */
113
 
  public String getToolTipText() {
114
 
    return m_ToolTipText;
115
 
  }
116
 
  
117
 
  /**
118
 
   * getter for the name to be displayed for this node
119
 
   * 
120
 
   * @return            the name
121
 
   */
122
 
  public String getName() {
123
 
    return m_Name;
124
 
  }
125
 
  
126
 
  /**
127
 
   * this returns the property editor that was provided for this object. This
128
 
   * propertyEditor object is initially chosen inside of the GenericObjectNode
129
 
   * updateTree() method if you are interested in where it comes from.
130
 
   * 
131
 
   * @return the default editor for this node
132
 
   */
133
 
  public PropertyEditor getPropertyEditor() {
134
 
    return m_PropertyEditor;
135
 
  }
136
 
  
137
 
  /**
138
 
   * returns a string representation
139
 
   * 
140
 
   * @return            a string representation
141
 
   */
142
 
  public String toString() {
143
 
    return getClass().getName() + "[" + getUserObject().toString() + "]";
144
 
  }
145
 
  
146
 
  /**
147
 
   * This method figures out what kind of parameter type this node 
148
 
   * represents and then creates the appropriate set of child nodes 
149
 
   * for editing.
150
 
   * 
151
 
   * @param name        the name
152
 
   * @param toolTipText the tooltip
153
 
   */
154
 
  public void addEditorNodes(String name, String toolTipText) {
155
 
    
156
 
    Object value = getUserObject();
157
 
    
158
 
    if (value instanceof Number) {
159
 
      
160
 
      NumberNode minNode = new NumberNode("min: ", (Number) value,
161
 
          NumberNode.NOT_ITERATOR, false, toolTipText);
162
 
      
163
 
      m_TreeModel.insertNodeInto(minNode, this, 0);
164
 
      
165
 
      Number one = null;
166
 
      try {
167
 
        one = minNode.getOneValue();
168
 
      } catch (NumberClassNotFoundException e) {
169
 
        e.printStackTrace();
170
 
      }
171
 
      
172
 
      NumberNode iteratorNode = new NumberNode("iterator: ", one,
173
 
          NumberNode.PLUS_EQUAL, true, toolTipText);
174
 
      m_TreeModel.insertNodeInto(iteratorNode, this, 1);
175
 
      
176
 
      NumberNode maxNode = new NumberNode("max: ", (Number) value,
177
 
          NumberNode.NOT_ITERATOR, true, toolTipText);
178
 
      m_TreeModel.insertNodeInto(maxNode, this, 2);
179
 
      
180
 
    } else if (m_PropertyEditor instanceof GenericObjectEditor) {
181
 
      
182
 
      GenericObjectNode classifierNode = new GenericObjectNode(
183
 
          m_ParentPanel, value,
184
 
          (GenericObjectEditor) m_PropertyEditor, toolTipText);
185
 
      
186
 
      m_TreeModel.insertNodeInto(classifierNode, this, 0);
187
 
      classifierNode.setTree(m_Tree);
188
 
      classifierNode.updateTree();
189
 
      
190
 
    } else if (m_PropertyEditor.getTags() != null) {
191
 
      
192
 
      String selected = m_PropertyEditor.getAsText();
193
 
      String tags[] = m_PropertyEditor.getTags();
194
 
      if (tags != null)
195
 
        for (int i = 0; i < tags.length; i++) {
196
 
          
197
 
          CheckBoxNode checkBoxNode = new CheckBoxNode(tags[i],
198
 
              selected.equals(tags[i]), toolTipText);
199
 
          m_TreeModel.insertNodeInto(checkBoxNode, this, i);
200
 
          
201
 
        }
202
 
      
203
 
    } else {
204
 
      
205
 
      DefaultNode defaultNode = new DefaultNode(name, toolTipText, value,
206
 
          m_PropertyEditor);
207
 
      
208
 
      m_TreeModel.insertNodeInto(defaultNode, this, 0);
209
 
      
210
 
    }
211
 
  }
212
 
  
213
 
  /** 
214
 
   * This method gets the range of values as specified by the 
215
 
   * child editor nodes.
216
 
   * 
217
 
   * @return    all values
218
 
   */
219
 
  public Vector getAllValues() {
220
 
    
221
 
    Vector values = new Vector();
222
 
    
223
 
    //OK, there are four type of nodes that can branch off of a propertyNode
224
 
    
225
 
    DefaultMutableTreeNode child = (DefaultMutableTreeNode) m_TreeModel.getChild(this, 0);
226
 
    
227
 
    if (child instanceof GenericObjectNode) {
228
 
      //Here we let the generic object class handles this for us
229
 
      values = ((GenericObjectNode) child).getValues();
230
 
      
231
 
    } else if (child instanceof DefaultNode) {
232
 
      //This is perhaps the easiest case.  GenericNodes are only responsible
233
 
      //for a single value                              
234
 
      values.add(((DefaultNode) child).getUserObject());
235
 
      
236
 
    } else if (child instanceof CheckBoxNode) {
237
 
      //Iterate through all of the children add their
238
 
      //value if they're selected
239
 
      
240
 
      int childCount = m_TreeModel.getChildCount(this);
241
 
      
242
 
      for (int i = 0; i < childCount; i++) {
243
 
        
244
 
        CheckBoxNode currentChild = (CheckBoxNode) m_TreeModel
245
 
        .getChild(this, i);
246
 
        
247
 
        if (currentChild.getSelected())
248
 
          values.add(currentChild.getUserObject());
249
 
        
250
 
      }
251
 
      
252
 
    } else if (child instanceof NumberNode) {
253
 
      //here we need to handle some weird cases for inpout validation
254
 
      
255
 
      NumberNode minChild = (NumberNode) m_TreeModel.getChild(this, 0);
256
 
      NumberNode iteratorChild = (NumberNode) m_TreeModel.getChild(this, 1);
257
 
      NumberNode maxChild = (NumberNode) m_TreeModel.getChild(this, 2);
258
 
      
259
 
      boolean ignoreIterator = false;
260
 
      
261
 
      try {
262
 
        
263
 
        if (iteratorChild.getSelected()) {
264
 
          
265
 
          //first we check to see if the min value is greater than the max value
266
 
          //if so then we gotta problem
267
 
          
268
 
          if (maxChild.lessThan(maxChild.getValue(), minChild.getValue())) {
269
 
            
270
 
            ignoreIterator = true;
271
 
            throw new InvalidInputException(
272
 
                "Invalid numeric input for node " + getName()
273
 
                + ": min > max. ");
274
 
          }
275
 
          
276
 
          //Make sure that the iterator value will actually "iterate" between the
277
 
          //min and max values
278
 
          if ((iteratorChild.getIteratorType() == NumberNode.PLUS_EQUAL)
279
 
              && (iteratorChild.lessThan(
280
 
                  iteratorChild.getValue(), iteratorChild
281
 
                  .getZeroValue()) || (iteratorChild
282
 
                      .equals(iteratorChild.getValue(),
283
 
                          iteratorChild.getZeroValue())))) {
284
 
            
285
 
            ignoreIterator = true;
286
 
            throw new InvalidInputException(
287
 
                "Invalid numeric input for node " + getName()
288
 
                + ": += iterator <= 0. ");
289
 
            
290
 
          } else if ((iteratorChild.getIteratorType() == NumberNode.TIMES_EQUAL)
291
 
              && (iteratorChild.lessThan(
292
 
                  iteratorChild.getValue(), iteratorChild
293
 
                  .getOneValue()) || (iteratorChild
294
 
                      .equals(iteratorChild.getValue(),
295
 
                          iteratorChild.getOneValue())))) {
296
 
            
297
 
            ignoreIterator = true;
298
 
            throw new InvalidInputException(
299
 
                "Invalid numeric input for node " + getName()
300
 
                + ": *= iterator <= 1. ");
301
 
            
302
 
          }
303
 
          
304
 
        }
305
 
        
306
 
      } catch (InvalidInputException e) {
307
 
        
308
 
        JRootPane parent = m_ParentPanel.getRootPane();
309
 
        
310
 
        JOptionPane.showMessageDialog(parent, "Invalid Input: "
311
 
            + e.getMessage(), "Input error",
312
 
            JOptionPane.ERROR_MESSAGE);
313
 
        
314
 
        e.printStackTrace();
315
 
      } catch (NumberClassNotFoundException e) {
316
 
        e.printStackTrace();
317
 
      }
318
 
      
319
 
      if (!iteratorChild.getSelected() || ignoreIterator) {
320
 
        //easiest case - if we don't care about the Iterator then we just throw
321
 
        //in the min value along with the max value(if its selected)  
322
 
        values.add(minChild.getUserObject());
323
 
        
324
 
        if (maxChild.getSelected()
325
 
            && (!maxChild.getValue().equals(minChild.getValue())))
326
 
          values.add(maxChild.getUserObject());
327
 
        
328
 
      } else {
329
 
        //here we need to cycle through all of the values from min to max in
330
 
        //increments specified by the inrement value.
331
 
        
332
 
        Number current = minChild.getValue();
333
 
        
334
 
        try {
335
 
          
336
 
          values.add(minChild.getValue());
337
 
          
338
 
          do {
339
 
            
340
 
            Number newNumber = null;
341
 
            
342
 
            if (iteratorChild.getIteratorType() == NumberNode.PLUS_EQUAL) {
343
 
              newNumber = iteratorChild.addNumbers(iteratorChild.getValue(), current);
344
 
            } else if (iteratorChild.getIteratorType() == NumberNode.TIMES_EQUAL) {
345
 
              newNumber = iteratorChild.multiplyNumbers(
346
 
                  iteratorChild.getValue(), current);
347
 
            }
348
 
            
349
 
            current = newNumber;
350
 
            
351
 
            if (iteratorChild
352
 
                .lessThan(current, maxChild.getValue())
353
 
                && (!iteratorChild.equals(current, maxChild.getValue()))) {
354
 
              values.add(newNumber);
355
 
            }
356
 
            
357
 
          } while (iteratorChild.lessThan(current, maxChild.getValue())
358
 
              && (!iteratorChild.equals(current, maxChild.getValue())));
359
 
          
360
 
          if (maxChild.getSelected()
361
 
              && (!maxChild.getValue().equals(minChild.getValue())))
362
 
            values.add(maxChild.getUserObject());
363
 
          
364
 
        } catch (Exception e) {
365
 
          e.printStackTrace();
366
 
        }
367
 
        
368
 
      }
369
 
    }
370
 
    
371
 
    return values;
372
 
  }
373
 
  
374
 
  /**
375
 
   * This method informs a child number node whether or not it is 
376
 
   * allowed to be selected. NumberNodes are the only ones that need
377
 
   * to ask permission first.  This simply makes sure that iterator
378
 
   * nodes can't be selected when the max node is not selected.
379
 
   * 
380
 
   * @param node        the node to check
381
 
   * @return            true of the node can be selected
382
 
   */
383
 
  public boolean canSelect(NumberNode node) {
384
 
    
385
 
    boolean permission = true;
386
 
    
387
 
    NumberNode iteratorChild = (NumberNode) m_TreeModel.getChild(this, 1);
388
 
    NumberNode maxChild = (NumberNode) m_TreeModel.getChild(this, 2);
389
 
    
390
 
    //the one case where we want to say no: you can not have an iterator
391
 
    //without a maximum value
392
 
    if (node == iteratorChild && (maxChild.getSelected() == false))
393
 
      permission = false;
394
 
    
395
 
    return permission;
396
 
  }
397
 
  
398
 
  /**
399
 
   * informs a requesting child node whether or not it has permission
400
 
   * to be deselected. Note that only NumberNodes and CheckBoxNodes
401
 
   * are the only one's that have any notion of being deselected and
402
 
   * therefore should be the only one's calling this method.
403
 
   * 
404
 
   * @param node        the node to check
405
 
   * @return            true if it can be de-selected
406
 
   */
407
 
  public boolean canDeselect(DefaultMutableTreeNode node) {
408
 
    
409
 
    boolean permission = true;
410
 
    
411
 
    if (node instanceof NumberNode) {
412
 
      
413
 
      NumberNode iteratorChild = (NumberNode) m_TreeModel.getChild(this,
414
 
          1);
415
 
      NumberNode maxChild = (NumberNode) m_TreeModel.getChild(this, 2);
416
 
      //the one case where we want to say no for number nodes: you can 
417
 
      //not have an iterator without a maximum value
418
 
      if (node == maxChild && (iteratorChild.getSelected() == true))
419
 
        permission = false;
420
 
      
421
 
    } else if (node instanceof CheckBoxNode) {
422
 
      
423
 
      //For check box nodes, we only want to say no if there's only one
424
 
      //box currently selected - because at least one box needs to be
425
 
      //checked.
426
 
      int totalSelected = 0;
427
 
      int childCount = m_TreeModel.getChildCount(this);
428
 
      
429
 
      for (int i = 0; i < childCount; i++) {
430
 
        
431
 
        CheckBoxNode currentChild = (CheckBoxNode) m_TreeModel
432
 
        .getChild(this, i);
433
 
        
434
 
        if (currentChild.getSelected())
435
 
          totalSelected++;
436
 
        
437
 
      }
438
 
      
439
 
      if (totalSelected == 1)
440
 
        permission = false;
441
 
      
442
 
    }
443
 
    
444
 
    return permission;
445
 
  }
446
 
}
 
 
b'\\ No newline at end of file'