Statistics
| Revision:

gvsig-scripting / trunk / org.gvsig.scripting.thing / src / main / java / thing / ThinletWorkarounds.java @ 4

History | View | Annotate | Download (9.61 KB)

1
// jEdit settings:
2
// :tabSize=4:indentSize=4:noTabs=true:folding=explicit:collapseFolds=1:
3

    
4
package thing;
5

    
6

    
7
import java.awt.AWTKeyStroke;
8
import java.awt.Color;
9
import java.awt.Font;
10
import java.util.Arrays;
11
import java.util.Enumeration;
12
import java.util.Hashtable;
13
import java.util.HashSet;
14
import java.util.NoSuchElementException;
15
import java.util.Set;
16
import java.util.StringTokenizer;
17

    
18
import thinlet.Thinlet;
19

    
20

    
21
/**
22
 * This class encapsulates workarounds for missing functionality in
23
 * Thinlet.java.
24
 * <p>
25
 * Some of Thinlet's private methods needed by ThinG are copied here and have
26
 * at times been sligtly modified. This methods need to be adapted when
27
 * their counterparts in Thinlet.java changes.
28
 * <p>
29
 * Some other helper methods are here, that should better be put into
30
 * Thinlet.java.
31
 *
32
 * @author Dirk Moebius
33
 */
34
public class ThinletWorkarounds
35
{
36
    //{{{ private methods copied from Thinlet.java
37
    /**
38
     * Copied from <code>Thinlet.java</code>:
39
     * Get a specified sub-component or component part. Key is e.g. "header" (table header),
40
     * ":parent" (parent component), ":comp" (head of a component list),
41
     * ":next" (next component in a list), "popupmenu" is a popupmenu, etc ...
42
     */
43
    static Object get(Object component, String key) {
44
        for (Object[] entry = (Object[]) component; entry != null;
45
        entry = (Object[]) entry[2]) {
46
            if (key.equals((String)entry[0])) {
47
                return entry[1];
48
            }
49
        }
50
        return null;
51
    }
52
    //}}}
53

    
54

    
55
    //{{{ methods missing in Thinlet.java
56
    /**
57
     * Gets the property value of the given component by the property key.
58
     * This method should really be in Thinlet.java.
59
     */
60
    public static Color getColor(Object component, String key)
61
    {
62
        return (Color) get(component, key);
63
    }
64

    
65

    
66
    /**
67
     * Gets the font of the given component, or the font of the thinlet, if
68
     * the font of the component has not been set explicitely.
69
     * This method should really be in Thinlet.java.
70
     */
71
    public static Font getFont(Thinlet thinlet, Object component, String key)
72
    {
73
        Font font = getFont(component, key);
74
        return font == null ? thinlet.getFont() : font;
75
    }
76

    
77

    
78
    /**
79
     * Gets the property value of the given component by the property key,
80
     * in this case, a font. In most cases, the property key is "font".
81
     * This method should really be in Thinlet.java.
82
     */
83
    public static Font getFont(Object component, String key)
84
    {
85
        return (Font) get(component, key);
86
    }
87

    
88

    
89
    /**
90
     *
91
     */
92
    public static AWTKeyStroke getKeystroke(Object component, String key)
93
    {
94
        Object value = get(component, key);
95
        if (value != null) {
96
            long keystroke = ((Long) value).longValue();
97
            int modifiers = (int) (keystroke >> 32);
98
            int keycode = (int) (keystroke & 0xffff);
99
            return AWTKeyStroke.getAWTKeyStroke(keycode, modifiers);
100
        }
101
        return null;
102
    }
103

    
104

    
105
    /**
106
     * Ripped off <code>Thinlet.addAttribute()</code>: returns a <code>Color</code>
107
     * object for a color description such as "#A0A0A0" or "0xA0A0A0" or
108
     * "240,240,240".
109
     */
110
    public static Color string2color(String value)
111
    {
112
        if(value == null) return null;
113
        if(value.length() == 0) return null;
114
        int color = 0;
115
        if (value.startsWith("#")) { color = Integer.parseInt(value.substring(1), 16); }
116
        else if (value.startsWith("0x")) { color = Integer.parseInt(value.substring(2), 16); }
117
        else { // three separated integer including red, green, and blue
118
            StringTokenizer st = new StringTokenizer(value, " \r\n\t,");
119
            color = 0xff000000 | ((Integer.parseInt(st.nextToken()) & 0xff) << 16) |
120
            ((Integer.parseInt(st.nextToken()) & 0xff) << 8) |
121
            (Integer.parseInt(st.nextToken()) & 0xff);
122
        }
123
        return new Color(color);
124
    }
125

    
126

    
127
    /**
128
     * Ripped off <code>Thinlet.addAttribute()</code>: returns a <code>Font</code>
129
     * object for a thinlet font description such as "Serif 10 bold italic".
130
     */
131
    public static Font string2font(Thinlet thinlet, String value)
132
    {
133
        Font font = thinlet.getFont(); // default thinlet font
134
        String name = null;
135
        boolean bold = false; boolean italic = false;
136
        int size = 0;
137
        StringTokenizer st = new StringTokenizer(value);
138
        while (st.hasMoreTokens()) {
139
            String token = st.nextToken();
140
            if ("bold".equalsIgnoreCase(token)) { bold = true; }
141
            else if ("italic".equalsIgnoreCase(token)) { italic = true; }
142
            else {
143
                try {
144
                    size = Integer.parseInt(token);
145
                } catch (NumberFormatException nfe) {
146
                    name = (name == null) ? token : (name + " " + token);
147
                }
148
            }
149
        }
150
        if (name == null) { name = font.getName(); }
151
        if (size == 0) { size = font.getSize(); }
152
        return new Font(name,
153
            (bold ? Font.BOLD : 0) | (italic ? Font.ITALIC : 0), size);
154
    }
155

    
156

    
157
    /**
158
     * Returns an enumeration of all client property keys defined in the
159
     * specified component.
160
     * This method should really be in Thinlet.java.
161
     */
162
    public static Enumeration getPropertyKeys(Object component)
163
    {
164
        Object table = get(component, ":bind");
165
        if(table != null)
166
            return ((Hashtable) table).keys();
167
        else
168
        {
169
            return new Enumeration()
170
            {
171
                public boolean hasMoreElements() { return false; }
172
                public Object nextElement() { throw new NoSuchElementException("empty enumeration"); }
173
            };
174
        }
175
    }
176

    
177

    
178
    /**
179
     * Gets all the components in this container.
180
     * <p>
181
     * The difference between <code>Thinlet.getItems(Object component)</code>
182
     * is the following: If the container is a tree, then recursively get
183
     * <i>all</i> nodes of the tree. (The Thinlet method only returns the
184
     * nodes of the top level).
185
     */
186
    public static Object[] getItems(Thinlet thinlet, Object component)
187
    {
188
        String classname = Thinlet.getClass(component);
189
        if(classname.equals("tree"))
190
        {
191
            Set result = new HashSet();
192
            getAllTreeItems(thinlet, component, result);
193
            return (Object[]) result.toArray(new Object[result.size()]);
194
        }
195
        else
196
            return thinlet.getItems(component);
197
    }
198

    
199

    
200
    /**
201
     * Returns the index of the specified item in the item list of the
202
     * specified component.
203
     * Note that trees are <i>not</i> searched recursively.
204
     * This method should really be in Thinlet.java.
205
     *
206
     * @param thinlet  the Thinlet
207
     * @param component  the component; this should be a component that
208
     *   has sub-items such as tree, table, node etc.
209
     * @param item  the item to search for.
210
     * @return the index of the item, or -1 if the item cannot be found.
211
     */
212
    public static int getIndexOfItem(Thinlet thinlet, Object component, Object item)
213
    {
214
        Object[] items = thinlet.getItems(component);
215
        for(int i = 0; i < items.length; ++i)
216
            if(item == items[i])
217
                return i;
218
        return -1;
219
    }
220

    
221

    
222
    /**
223
     * Sets the selected item of the specified component, deselects all others.
224
     * This method should really be in Thinlet.java.
225
     */
226
    public static void setSelectedItem(Thinlet thinlet, Object component, Object item)
227
    {
228
        Object[] items = getItems(thinlet, component);
229
        if(items != null)
230
        {
231
            for(int i = 0; i < items.length; ++i)
232
                thinlet.setBoolean(items[i], "selected", items[i] == item);
233
        }
234
    }
235

    
236

    
237
    /**
238
     * Returns the total count of all sub-components of the specified
239
     * components, including the children's children, recursively.
240
     */
241
    public static int getTotalCount(Thinlet thinlet, Object component)
242
    {
243
        class CountVisitor implements ComponentWalker.Visitor
244
        {
245
            int count = 0;
246
            public boolean visit(Object component, int depth) { count++; return true; }
247
            public void leave(Object component, int depth) {}
248
        }
249

    
250
        CountVisitor visitor = new CountVisitor();
251
        new ComponentWalker().walk(thinlet, component, visitor);
252
        return visitor.count;
253
    }
254

    
255

    
256
    /**
257
     * Returns a short string representation of the specified component,
258
     * for example "button:btnOk". Useful for debugging output.
259
     *
260
     * @param component  the component. If it is null, the string "null" is
261
     *                   returned.
262
     * @return a string representation of the component.
263
     */
264
    public static String toString(Object component)
265
    {
266
        if(component == null)
267
            return "null";
268
        StringBuffer buf = new StringBuffer("[");
269
        String classname = Thinlet.getClass(component);
270
        if(classname == null)
271
            buf.append("not a component: ").append(component.toString());
272
        else
273
        {
274
            buf.append(classname);
275
            String name = (String) get(component, "name");
276
            if(name != null)
277
                buf.append(':').append(name);
278
        }
279
        buf.append(']');
280
        return buf.toString();
281
    }
282
    //}}}
283

    
284

    
285
    //{{{ private helper methods
286
    private static void getAllTreeItems(Thinlet thinlet, Object component, Set result)
287
    {
288
        Object[] items = thinlet.getItems(component);
289
        result.addAll(Arrays.asList(items));
290
        for(int i = 0; i < items.length; ++i)
291
        {
292
            String classname = Thinlet.getClass(items[i]);
293
            if(classname.equals("node"))
294
                getAllTreeItems(thinlet, items[i], result);
295
        }
296
    }
297
    //}}}
298

    
299
}
300