rubyjs 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +128 -0
- data/Rakefile +9 -0
- data/bin/rubyjs +140 -0
- data/examples/ex1/Rakefile +7 -0
- data/examples/ex1/ex1.js +771 -0
- data/examples/ex1/ex1.rb +42 -0
- data/examples/ex1/index.html +7 -0
- data/examples/hw/Rakefile +9 -0
- data/examples/hw/hw.js +635 -0
- data/examples/hw/hw.rb +7 -0
- data/examples/hw/index.html +7 -0
- data/patches/parse_tree.rb.diff +34 -0
- data/rubyjs.gemspec +24 -0
- data/src/rubyjs.rb +4 -0
- data/src/rubyjs/code_generator.rb +474 -0
- data/src/rubyjs/compiler.rb +2007 -0
- data/src/rubyjs/debug_name_generator.rb +75 -0
- data/src/rubyjs/encoder.rb +171 -0
- data/src/rubyjs/eval_into.rb +59 -0
- data/src/rubyjs/lib/core.rb +1008 -0
- data/src/rubyjs/lib/json.rb +101 -0
- data/src/rubyjs/model.rb +287 -0
- data/src/rubyjs/name_generator.rb +71 -0
- data/src/rwt/AbsolutePanel.rb +161 -0
- data/src/rwt/DOM.Konqueror.rb +89 -0
- data/src/rwt/DOM.Opera.rb +65 -0
- data/src/rwt/DOM.rb +1044 -0
- data/src/rwt/Event.Opera.rb +35 -0
- data/src/rwt/Event.rb +429 -0
- data/src/rwt/HTTPRequest.IE6.rb +5 -0
- data/src/rwt/HTTPRequest.rb +74 -0
- data/src/rwt/Label.rb +164 -0
- data/src/rwt/Panel.rb +90 -0
- data/src/rwt/RootPanel.rb +16 -0
- data/src/rwt/UIObject.rb +495 -0
- data/src/rwt/Widget.rb +193 -0
- data/src/rwt/ported-from/AbsolutePanel.java +158 -0
- data/src/rwt/ported-from/DOM.java +571 -0
- data/src/rwt/ported-from/DOMImpl.java +426 -0
- data/src/rwt/ported-from/DOMImplOpera.java +82 -0
- data/src/rwt/ported-from/DOMImplStandard.java +234 -0
- data/src/rwt/ported-from/HTTPRequest.java +81 -0
- data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
- data/src/rwt/ported-from/Label.java +163 -0
- data/src/rwt/ported-from/Panel.java +99 -0
- data/src/rwt/ported-from/UIObject.java +614 -0
- data/src/rwt/ported-from/Widget.java +221 -0
- data/test/benchmark/bm_call_conv1.js +16 -0
- data/test/benchmark/bm_call_conv2.js +14 -0
- data/test/benchmark/bm_var_acc1.js +13 -0
- data/test/benchmark/bm_var_acc2.js +11 -0
- data/test/benchmark/bm_vm1_block.js +15 -0
- data/test/benchmark/bm_vm1_block.rb +15 -0
- data/test/benchmark/bm_vm1_const.js +13 -0
- data/test/benchmark/bm_vm1_const.rb +13 -0
- data/test/benchmark/bm_vm1_ensure.js +17 -0
- data/test/benchmark/bm_vm1_ensure.rb +15 -0
- data/test/benchmark/common.js +4 -0
- data/test/benchmark/common.rb +5 -0
- data/test/benchmark/params.yaml +7 -0
- data/test/browser.test.html +4059 -0
- data/test/browser.test.js +3225 -0
- data/test/common.Browser.rb +13 -0
- data/test/common.rb +8 -0
- data/test/gen_browser_test_suite.rb +129 -0
- data/test/gen_test_suite.rb +41 -0
- data/test/run_benchs.rb +58 -0
- data/test/run_tests.rb +22 -0
- data/test/test_args.rb +24 -0
- data/test/test_array.rb +26 -0
- data/test/test_case.rb +35 -0
- data/test/test_class.rb +55 -0
- data/test/test_eql.rb +9 -0
- data/test/test_exception.rb +61 -0
- data/test/test_expr.rb +12 -0
- data/test/test_hash.rb +29 -0
- data/test/test_if.rb +28 -0
- data/test/test_inspect.rb +10 -0
- data/test/test_lebewesen.rb +39 -0
- data/test/test_massign.rb +66 -0
- data/test/test_new.rb +12 -0
- data/test/test_range.rb +53 -0
- data/test/test_regexp.rb +22 -0
- data/test/test_send.rb +65 -0
- data/test/test_simple_output.rb +5 -0
- data/test/test_splat.rb +21 -0
- data/test/test_string.rb +51 -0
- data/test/test_yield.rb +152 -0
- data/utils/js/Makefile +9 -0
- data/utils/js/RunScript.class +0 -0
- data/utils/js/RunScript.java +73 -0
- data/utils/js/js.jar +0 -0
- data/utils/js/run.sh +3 -0
- data/utils/jsc/Makefile +7 -0
- data/utils/jsc/README +3 -0
- data/utils/jsc/RunScript.c +93 -0
- data/utils/jsc/run.sh +15 -0
- data/utils/yuicompressor/README +1 -0
- data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
- data/vendor/ParseTree-1.7.1-patched/History.txt +217 -0
- data/vendor/ParseTree-1.7.1-patched/Manifest.txt +22 -0
- data/vendor/ParseTree-1.7.1-patched/README.txt +110 -0
- data/vendor/ParseTree-1.7.1-patched/Rakefile +41 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_abc +89 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_audit +28 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_deps +62 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_show +49 -0
- data/vendor/ParseTree-1.7.1-patched/demo/printer.rb +20 -0
- data/vendor/ParseTree-1.7.1-patched/lib/composite_sexp_processor.rb +49 -0
- data/vendor/ParseTree-1.7.1-patched/lib/parse_tree.rb +1013 -0
- data/vendor/ParseTree-1.7.1-patched/lib/sexp.rb +235 -0
- data/vendor/ParseTree-1.7.1-patched/lib/sexp_processor.rb +330 -0
- data/vendor/ParseTree-1.7.1-patched/lib/unique.rb +15 -0
- data/vendor/ParseTree-1.7.1-patched/test/pt_testcase.rb +1221 -0
- data/vendor/ParseTree-1.7.1-patched/test/something.rb +53 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_all.rb +13 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_composite_sexp_processor.rb +69 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_parse_tree.rb +216 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_sexp.rb +291 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_sexp_processor.rb +244 -0
- data/vendor/ParseTree-1.7.1-patched/validate.sh +31 -0
- data/vendor/ParseTree-1.7.1/History.txt +217 -0
- data/vendor/ParseTree-1.7.1/Manifest.txt +22 -0
- data/vendor/ParseTree-1.7.1/README.txt +110 -0
- data/vendor/ParseTree-1.7.1/Rakefile +41 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_abc +89 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_audit +28 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_deps +62 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_show +49 -0
- data/vendor/ParseTree-1.7.1/demo/printer.rb +20 -0
- data/vendor/ParseTree-1.7.1/lib/composite_sexp_processor.rb +49 -0
- data/vendor/ParseTree-1.7.1/lib/parse_tree.rb +1004 -0
- data/vendor/ParseTree-1.7.1/lib/sexp.rb +235 -0
- data/vendor/ParseTree-1.7.1/lib/sexp_processor.rb +330 -0
- data/vendor/ParseTree-1.7.1/lib/unique.rb +15 -0
- data/vendor/ParseTree-1.7.1/test/pt_testcase.rb +1221 -0
- data/vendor/ParseTree-1.7.1/test/something.rb +53 -0
- data/vendor/ParseTree-1.7.1/test/test_all.rb +13 -0
- data/vendor/ParseTree-1.7.1/test/test_composite_sexp_processor.rb +69 -0
- data/vendor/ParseTree-1.7.1/test/test_parse_tree.rb +216 -0
- data/vendor/ParseTree-1.7.1/test/test_sexp.rb +291 -0
- data/vendor/ParseTree-1.7.1/test/test_sexp_processor.rb +244 -0
- data/vendor/ParseTree-1.7.1/validate.sh +31 -0
- metadata +230 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2006 Google Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
5
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
6
|
+
* the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
* License for the specific language governing permissions and limitations under
|
14
|
+
* the License.
|
15
|
+
*/
|
16
|
+
package com.google.gwt.user.client.ui;
|
17
|
+
|
18
|
+
import com.google.gwt.user.client.DOM;
|
19
|
+
import com.google.gwt.user.client.Element;
|
20
|
+
|
21
|
+
import java.util.Iterator;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Abstract base class for all panels, which are widgets that can contain other
|
25
|
+
* widgets.
|
26
|
+
*/
|
27
|
+
public abstract class Panel extends Widget implements HasWidgets {
|
28
|
+
|
29
|
+
public void add(Widget w) {
|
30
|
+
throw new UnsupportedOperationException("This panel does not support no-arg add()");
|
31
|
+
}
|
32
|
+
|
33
|
+
public void clear() {
|
34
|
+
Iterator it = iterator();
|
35
|
+
while (it.hasNext()) {
|
36
|
+
it.next();
|
37
|
+
it.remove();
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* This method must be called as part of the add method of any panel. It
|
43
|
+
* ensures that the Widget's parent is set properly, and that it is removed
|
44
|
+
* from any existing parent widget. It also attaches the child widget's
|
45
|
+
* DOM element to its new container, ensuring that this process occurs in the
|
46
|
+
* right order.
|
47
|
+
*
|
48
|
+
* @param w the widget to be adopted
|
49
|
+
* @param container the element within which it will be contained
|
50
|
+
*/
|
51
|
+
protected void adopt(Widget w, Element container) {
|
52
|
+
// Remove the widget from its current parent, if any.
|
53
|
+
w.removeFromParent();
|
54
|
+
|
55
|
+
// Attach it at the DOM and GWT levels.
|
56
|
+
if (container != null) {
|
57
|
+
DOM.appendChild(container, w.getElement());
|
58
|
+
}
|
59
|
+
w.setParent(this);
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* This method must be called whenever a Widget is removed. It ensures that
|
64
|
+
* the Widget's parent is cleared.
|
65
|
+
*
|
66
|
+
* @param w the widget to be disowned
|
67
|
+
*/
|
68
|
+
protected void disown(Widget w) {
|
69
|
+
// Only disown it if it's actually contained in this panel.
|
70
|
+
if (w.getParent() != this) {
|
71
|
+
throw new IllegalArgumentException("w is not a child of this panel");
|
72
|
+
}
|
73
|
+
|
74
|
+
// Remove it at the DOM and GWT levels.
|
75
|
+
Element elem = w.getElement();
|
76
|
+
w.setParent(null);
|
77
|
+
DOM.removeChild(DOM.getParent(elem), elem);
|
78
|
+
}
|
79
|
+
|
80
|
+
protected void onAttach() {
|
81
|
+
super.onAttach();
|
82
|
+
|
83
|
+
// Ensure that all child widgets are attached.
|
84
|
+
for (Iterator it = iterator(); it.hasNext();) {
|
85
|
+
Widget child = (Widget) it.next();
|
86
|
+
child.onAttach();
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
protected void onDetach() {
|
91
|
+
super.onDetach();
|
92
|
+
|
93
|
+
// Ensure that all child widgets are detached.
|
94
|
+
for (Iterator it = iterator(); it.hasNext();) {
|
95
|
+
Widget child = (Widget) it.next();
|
96
|
+
child.onDetach();
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
@@ -0,0 +1,614 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2007 Google Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
5
|
+
* use this file except in compliance with the License. You may obtain a copy of
|
6
|
+
* the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
* License for the specific language governing permissions and limitations under
|
14
|
+
* the License.
|
15
|
+
*/
|
16
|
+
package com.google.gwt.user.client.ui;
|
17
|
+
|
18
|
+
import com.google.gwt.user.client.DOM;
|
19
|
+
import com.google.gwt.user.client.Element;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* The superclass for all user-interface objects. It simply wraps a DOM element,
|
23
|
+
* and cannot receive events. Most interesting user-interface classes derive
|
24
|
+
* from {@link com.google.gwt.user.client.ui.Widget}.
|
25
|
+
*
|
26
|
+
* <h3>Styling With CSS</h3>
|
27
|
+
* <p>
|
28
|
+
* All <code>UIObject</code> objects can be styled using CSS. Style names that
|
29
|
+
* are specified programmatically in Java source are implicitly associated with
|
30
|
+
* CSS style rules. In terms of HTML and CSS, a GWT style name is the element's
|
31
|
+
* CSS "class". By convention, GWT style names are of the form
|
32
|
+
* <code>[project]-[widget]</code>.
|
33
|
+
* </p>
|
34
|
+
*
|
35
|
+
* <p>
|
36
|
+
* For example, the {@link Button} widget has the style name
|
37
|
+
* <code>gwt-Button</code>, meaning that within the <code>Button</code>
|
38
|
+
* constructor, the following call occurs:
|
39
|
+
*
|
40
|
+
* <pre class="code">
|
41
|
+
* setStyleName("gwt-Button");</pre>
|
42
|
+
*
|
43
|
+
* A corresponding CSS style rule can then be written as follows:
|
44
|
+
*
|
45
|
+
* <pre class="code">
|
46
|
+
* // Example of how you might choose to style a Button widget
|
47
|
+
* .gwt-Button {
|
48
|
+
* background-color: yellow;
|
49
|
+
* color: black;
|
50
|
+
* font-size: 24pt;
|
51
|
+
* }</pre>
|
52
|
+
*
|
53
|
+
* Note the dot prefix in the CSS style rule. This syntax is called a <a
|
54
|
+
* href="http://www.w3.org/TR/REC-CSS2/selector.html#class-html">CSS class
|
55
|
+
* selector</a>.
|
56
|
+
* </p>
|
57
|
+
*
|
58
|
+
* <h3>Style Name Specifics</h3>
|
59
|
+
* <p>
|
60
|
+
* Every <code>UIObject</code> has a <i>primary style name</i> that
|
61
|
+
* identifies the key CSS style rule that should always be applied to it. Use
|
62
|
+
* {@link #setStyleName(String)} to specify an object's primary style name. In
|
63
|
+
* most cases, the primary style name is set in a widget's constructor and never
|
64
|
+
* changes again during execution. In the case that no primary style name is
|
65
|
+
* specified, it defaults to <code>gwt-nostyle</code>.
|
66
|
+
* </p>
|
67
|
+
*
|
68
|
+
* <p>
|
69
|
+
* More complex styling behavior can be achieved by manipulating an object's
|
70
|
+
* <i>secondary style names</i>. Secondary style names can be added and removed
|
71
|
+
* using {@link #addStyleName(String)} and {@link #removeStyleName(String)}.
|
72
|
+
* The purpose of secondary style names is to associate a variety of CSS style
|
73
|
+
* rules over time as an object progresses through different visual states.
|
74
|
+
* </p>
|
75
|
+
*
|
76
|
+
* <p>
|
77
|
+
* There is an important special formulation of secondary style names called
|
78
|
+
* <i>dependent style names</i>. A dependent style name is a secondary style
|
79
|
+
* name prefixed with the primary style name of the widget itself. See
|
80
|
+
* {@link #addStyleName(String)} for details.
|
81
|
+
* </p>
|
82
|
+
*/
|
83
|
+
public abstract class UIObject {
|
84
|
+
|
85
|
+
private static final String EMPTY_STYLENAME_MSG = "Style names cannot be empty";
|
86
|
+
|
87
|
+
private static final String NULL_HANDLE_MSG = "Null widget handle. If you "
|
88
|
+
+ "are creating a composite, ensure that initWidget() has been called.";
|
89
|
+
|
90
|
+
private static final String STYLE_EMPTY = "gwt-nostyle";
|
91
|
+
|
92
|
+
public static native boolean isVisible(Element elem) /*-{
|
93
|
+
return (elem.style.display != 'none');
|
94
|
+
}-*/;
|
95
|
+
|
96
|
+
public static native void setVisible(Element elem, boolean visible) /*-{
|
97
|
+
elem.style.display = visible ? '' : 'none';
|
98
|
+
}-*/;
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Sets the object's primary style name and updates all dependent style names.
|
102
|
+
*
|
103
|
+
* @param elem the element whose style is to be reset
|
104
|
+
* @param style the new primary style name
|
105
|
+
* @see #setStyleName(Element, String, boolean)
|
106
|
+
*/
|
107
|
+
protected static void resetStyleName(Element elem, String style) {
|
108
|
+
if (elem == null) {
|
109
|
+
throw new RuntimeException(NULL_HANDLE_MSG);
|
110
|
+
}
|
111
|
+
|
112
|
+
// Style names cannot contain leading or trailing whitespace, and cannot
|
113
|
+
// legally be empty.
|
114
|
+
style = style.trim();
|
115
|
+
if (style.length() == 0) {
|
116
|
+
throw new IllegalArgumentException(EMPTY_STYLENAME_MSG);
|
117
|
+
}
|
118
|
+
|
119
|
+
ensurePrimaryStyleName(elem);
|
120
|
+
updatePrimaryAndDependentStyleNames(elem, style);
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* This convenience method adds or removes a secondary style name to the
|
125
|
+
* primary style name for a given element. Set {@link #setStyleName(String)}
|
126
|
+
* for a description of how primary and secondary style names are used.
|
127
|
+
*
|
128
|
+
* @param elem the element whose style is to be modified
|
129
|
+
* @param style the secondary style name to be added or removed
|
130
|
+
* @param add <code>true</code> to add the given style, <code>false</code>
|
131
|
+
* to remove it
|
132
|
+
*/
|
133
|
+
protected static void setStyleName(Element elem, String style, boolean add) {
|
134
|
+
if (elem == null) {
|
135
|
+
throw new RuntimeException(NULL_HANDLE_MSG);
|
136
|
+
}
|
137
|
+
|
138
|
+
style = style.trim();
|
139
|
+
if (style.length() == 0) {
|
140
|
+
throw new IllegalArgumentException(EMPTY_STYLENAME_MSG);
|
141
|
+
}
|
142
|
+
|
143
|
+
// Get the current style string.
|
144
|
+
String oldStyle = ensurePrimaryStyleName(elem);
|
145
|
+
int idx;
|
146
|
+
if (oldStyle == null) {
|
147
|
+
idx = -1;
|
148
|
+
oldStyle = "";
|
149
|
+
} else {
|
150
|
+
idx = oldStyle.indexOf(style);
|
151
|
+
}
|
152
|
+
|
153
|
+
// Calculate matching index.
|
154
|
+
while (idx != -1) {
|
155
|
+
if (idx == 0 || oldStyle.charAt(idx - 1) == ' ') {
|
156
|
+
int last = idx + style.length();
|
157
|
+
int lastPos = oldStyle.length();
|
158
|
+
if ((last == lastPos)
|
159
|
+
|| ((last < lastPos) && (oldStyle.charAt(last) == ' '))) {
|
160
|
+
break;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
idx = oldStyle.indexOf(style, idx + 1);
|
164
|
+
}
|
165
|
+
|
166
|
+
if (add) {
|
167
|
+
// Only add the style if it's not already present.
|
168
|
+
if (idx == -1) {
|
169
|
+
if (oldStyle.length() > 0) {
|
170
|
+
oldStyle += " ";
|
171
|
+
}
|
172
|
+
DOM.setElementProperty(elem, "className", oldStyle + style);
|
173
|
+
}
|
174
|
+
} else {
|
175
|
+
// Don't try to remove the style if it's not there.
|
176
|
+
if (idx != -1) {
|
177
|
+
if (idx == 0) {
|
178
|
+
// You can't remove the base (i.e. the first) style name.
|
179
|
+
throw new IllegalArgumentException("Cannot remove base style name");
|
180
|
+
}
|
181
|
+
String begin = oldStyle.substring(0, idx);
|
182
|
+
String end = oldStyle.substring(idx + style.length());
|
183
|
+
DOM.setElementProperty(elem, "className", begin + end);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
/**
|
189
|
+
* Ensure that the root element has a primary style name. If one is not
|
190
|
+
* already present, then it is assigned the default style name.
|
191
|
+
*
|
192
|
+
* @return the primary style name
|
193
|
+
*/
|
194
|
+
private static String ensurePrimaryStyleName(Element elem) {
|
195
|
+
String className = DOM.getElementProperty(elem, "className").trim();
|
196
|
+
|
197
|
+
if ("".equals(className)) {
|
198
|
+
className = STYLE_EMPTY;
|
199
|
+
DOM.setElementProperty(elem, "className", className);
|
200
|
+
}
|
201
|
+
|
202
|
+
return className;
|
203
|
+
}
|
204
|
+
|
205
|
+
/**
|
206
|
+
* Replaces all instances of the primary style name with newPrimaryStyleName.
|
207
|
+
*/
|
208
|
+
private static native void updatePrimaryAndDependentStyleNames(Element elem, String newStyle) /*-{
|
209
|
+
var className = elem.className;
|
210
|
+
|
211
|
+
var spaceIdx = className.indexOf(' ');
|
212
|
+
if (spaceIdx >= 0) {
|
213
|
+
// Get the old base style name from the beginning of the className.
|
214
|
+
var oldStyle = className.substring(0, spaceIdx);
|
215
|
+
|
216
|
+
// Replace oldStyle with newStyle. We have to do this by hand because
|
217
|
+
// there is no String.replaceAll() and String.replace() takes a regex,
|
218
|
+
// which we can't guarantee is safe on arbitrary class names.
|
219
|
+
var newClassName = '', curIdx = 0;
|
220
|
+
while (true) {
|
221
|
+
var idx = className.indexOf(oldStyle, curIdx);
|
222
|
+
if (idx == -1) {
|
223
|
+
newClassName += className.substring(curIdx);
|
224
|
+
break;
|
225
|
+
}
|
226
|
+
|
227
|
+
newClassName += className.substring(curIdx, idx);
|
228
|
+
newClassName += newStyle;
|
229
|
+
curIdx = idx + oldStyle.length;
|
230
|
+
}
|
231
|
+
|
232
|
+
elem.className = newClassName;
|
233
|
+
} else {
|
234
|
+
// There was no space, and therefore only one class name, which we can
|
235
|
+
// simply clobber.
|
236
|
+
elem.className = newStyle;
|
237
|
+
}
|
238
|
+
}-*/;
|
239
|
+
|
240
|
+
private Element element;
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Adds a secondary or dependent style name to this object. A secondary style
|
244
|
+
* name is an additional style name that is, in HTML/CSS terms, included as a
|
245
|
+
* space-separated token in the value of the CSS <code>class</code>
|
246
|
+
* attribute for this object's root element.
|
247
|
+
*
|
248
|
+
* <p>
|
249
|
+
* The most important use for this method is to add a special kind of
|
250
|
+
* secondary style name called a <i>dependent style name</i>. To add a
|
251
|
+
* dependent style name, prefix the 'style' argument with the result of
|
252
|
+
* {@link #getStyleName()}. For example, suppose the primary style name is
|
253
|
+
* <code>gwt-TextBox</code>. If the following method is called as
|
254
|
+
* <code>obj.setReadOnly(true)</code>:
|
255
|
+
* </p>
|
256
|
+
*
|
257
|
+
* <pre class="code">
|
258
|
+
* public void setReadOnly(boolean readOnly) {
|
259
|
+
* isReadOnlyMode = readOnly;
|
260
|
+
*
|
261
|
+
* // Create a dependent style name.
|
262
|
+
* String readOnlyStyle = getStyleName() + "-readonly";
|
263
|
+
*
|
264
|
+
* if (readOnly) {
|
265
|
+
* addStyleName(readOnlyStyle);
|
266
|
+
* } else {
|
267
|
+
* removeStyleName(readOnlyStyle);
|
268
|
+
* }
|
269
|
+
* }</pre>
|
270
|
+
*
|
271
|
+
* <p>
|
272
|
+
* then both of the CSS style rules below will be applied:
|
273
|
+
* </p>
|
274
|
+
*
|
275
|
+
* <pre class="code">
|
276
|
+
*
|
277
|
+
* // This rule is based on the primary style name and is always active.
|
278
|
+
* .gwt-TextBox {
|
279
|
+
* font-size: 12pt;
|
280
|
+
* }
|
281
|
+
*
|
282
|
+
* // This rule is based on a dependent style name that is only active
|
283
|
+
* // when the widget has called addStyleName(getStyleName() + "-readonly").
|
284
|
+
* .gwt-TextBox-readonly {
|
285
|
+
* background-color: lightgrey;
|
286
|
+
* border: none;
|
287
|
+
* }</pre>
|
288
|
+
*
|
289
|
+
* <p>
|
290
|
+
* Dependent style names are powerful because they are automatically updated
|
291
|
+
* whenever the primary style name changes. Continuing with the example above,
|
292
|
+
* if the primary style name changed due to the following call:
|
293
|
+
* </p>
|
294
|
+
*
|
295
|
+
* <pre class="code">setStyleName("my-TextThingy");</pre>
|
296
|
+
*
|
297
|
+
* <p>
|
298
|
+
* then the object would be re-associated with style rules below rather than
|
299
|
+
* those above:
|
300
|
+
* </p>
|
301
|
+
*
|
302
|
+
* <pre class="code">
|
303
|
+
* .my-TextThingy {
|
304
|
+
* font-size: 12pt;
|
305
|
+
* }
|
306
|
+
*
|
307
|
+
* .my-TextThingy-readonly {
|
308
|
+
* background-color: lightgrey;
|
309
|
+
* border: none;
|
310
|
+
* }</pre>
|
311
|
+
*
|
312
|
+
* <p>
|
313
|
+
* Secondary style names that are not dependent style names are not
|
314
|
+
* automatically updated when the primary style name changes.
|
315
|
+
* </p>
|
316
|
+
*
|
317
|
+
* @param style the secondary style name to be added
|
318
|
+
* @see UIObject
|
319
|
+
* @see #removeStyleName(String)
|
320
|
+
*/
|
321
|
+
public void addStyleName(String style) {
|
322
|
+
setStyleName(getStyleElement(), style, true);
|
323
|
+
}
|
324
|
+
|
325
|
+
/**
|
326
|
+
* Gets the object's absolute left position in pixels, as measured from the
|
327
|
+
* browser window's client area.
|
328
|
+
*
|
329
|
+
* @return the object's absolute left position
|
330
|
+
*/
|
331
|
+
public int getAbsoluteLeft() {
|
332
|
+
return DOM.getAbsoluteLeft(getElement());
|
333
|
+
}
|
334
|
+
|
335
|
+
/**
|
336
|
+
* Gets the object's absolute top position in pixels, as measured from the
|
337
|
+
* browser window's client area.
|
338
|
+
*
|
339
|
+
* @return the object's absolute top position
|
340
|
+
*/
|
341
|
+
public int getAbsoluteTop() {
|
342
|
+
return DOM.getAbsoluteTop(getElement());
|
343
|
+
}
|
344
|
+
|
345
|
+
/**
|
346
|
+
* Gets a handle to the object's underlying DOM element.
|
347
|
+
*
|
348
|
+
* @return the object's browser element
|
349
|
+
*/
|
350
|
+
public Element getElement() {
|
351
|
+
return element;
|
352
|
+
}
|
353
|
+
|
354
|
+
/**
|
355
|
+
* Gets the object's offset height in pixels. This is the total height of the
|
356
|
+
* object, including decorations such as border, margin, and padding.
|
357
|
+
*
|
358
|
+
* @return the object's offset height
|
359
|
+
*/
|
360
|
+
public int getOffsetHeight() {
|
361
|
+
return DOM.getElementPropertyInt(element, "offsetHeight");
|
362
|
+
}
|
363
|
+
|
364
|
+
/**
|
365
|
+
* Gets the object's offset width in pixels. This is the total width of the
|
366
|
+
* object, including decorations such as border, margin, and padding.
|
367
|
+
*
|
368
|
+
* @return the object's offset width
|
369
|
+
*/
|
370
|
+
public int getOffsetWidth() {
|
371
|
+
return DOM.getElementPropertyInt(element, "offsetWidth");
|
372
|
+
}
|
373
|
+
|
374
|
+
/**
|
375
|
+
* Gets the primary style name associated with the object.
|
376
|
+
*
|
377
|
+
* @return the object's primary style name
|
378
|
+
* @see #setStyleName(String)
|
379
|
+
* @see #addStyleName(String)
|
380
|
+
* @see #removeStyleName(String)
|
381
|
+
*/
|
382
|
+
public String getStyleName() {
|
383
|
+
String fullClassName = ensurePrimaryStyleName(getStyleElement());
|
384
|
+
|
385
|
+
// The base style name is always the first token of the full CSS class
|
386
|
+
// name. There can be no leading whitespace in the class name, so it's not
|
387
|
+
// necessary to trim() it.
|
388
|
+
int spaceIdx = fullClassName.indexOf(' ');
|
389
|
+
if (spaceIdx >= 0) {
|
390
|
+
return fullClassName.substring(0, spaceIdx);
|
391
|
+
}
|
392
|
+
return fullClassName;
|
393
|
+
}
|
394
|
+
|
395
|
+
/**
|
396
|
+
* Gets the title associated with this object. The title is the 'tool-tip'
|
397
|
+
* displayed to users when they hover over the object.
|
398
|
+
*
|
399
|
+
* @return the object's title
|
400
|
+
*/
|
401
|
+
public String getTitle() {
|
402
|
+
return DOM.getElementProperty(element, "title");
|
403
|
+
}
|
404
|
+
|
405
|
+
/**
|
406
|
+
* Determines whether or not this object is visible.
|
407
|
+
*
|
408
|
+
* @return <code>true</code> if the object is visible
|
409
|
+
*/
|
410
|
+
public boolean isVisible() {
|
411
|
+
return isVisible(element);
|
412
|
+
}
|
413
|
+
|
414
|
+
/**
|
415
|
+
* Removes a secondary style name.
|
416
|
+
*
|
417
|
+
* @param style the secondary style name to be removed
|
418
|
+
* @see #addStyleName(String)
|
419
|
+
*/
|
420
|
+
public void removeStyleName(String style) {
|
421
|
+
setStyleName(getStyleElement(), style, false);
|
422
|
+
}
|
423
|
+
|
424
|
+
/**
|
425
|
+
* Sets the object's height. This height does not include decorations such as
|
426
|
+
* border, margin, and padding.
|
427
|
+
*
|
428
|
+
* @param height the object's new height, in CSS units (e.g. "10px", "1em")
|
429
|
+
*/
|
430
|
+
public void setHeight(String height) {
|
431
|
+
// This exists to deal with an inconsistency in IE's implementation where
|
432
|
+
// it won't accept negative numbers in length measurements
|
433
|
+
assert extractLengthValue(height.trim().toLowerCase()) >= 0 :
|
434
|
+
"CSS heights should not be negative";
|
435
|
+
DOM.setStyleAttribute(element, "height", height);
|
436
|
+
}
|
437
|
+
|
438
|
+
/**
|
439
|
+
* Sets the object's size, in pixels, not including decorations such as
|
440
|
+
* border, margin, and padding.
|
441
|
+
*
|
442
|
+
* @param width the object's new width, in pixels
|
443
|
+
* @param height the object's new height, in pixels
|
444
|
+
*/
|
445
|
+
public void setPixelSize(int width, int height) {
|
446
|
+
if (width >= 0) {
|
447
|
+
setWidth(width + "px");
|
448
|
+
}
|
449
|
+
if (height >= 0) {
|
450
|
+
setHeight(height + "px");
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
/**
|
455
|
+
* Sets the object's size. This size does not include decorations such as
|
456
|
+
* border, margin, and padding.
|
457
|
+
*
|
458
|
+
* @param width the object's new width, in CSS units (e.g. "10px", "1em")
|
459
|
+
* @param height the object's new height, in CSS units (e.g. "10px", "1em")
|
460
|
+
*/
|
461
|
+
public void setSize(String width, String height) {
|
462
|
+
setWidth(width);
|
463
|
+
setHeight(height);
|
464
|
+
}
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Sets the object's primary style name and updates all dependent style names.
|
468
|
+
*
|
469
|
+
* @param style the new primary style name
|
470
|
+
* @see #addStyleName(String)
|
471
|
+
* @see #removeStyleName(String)
|
472
|
+
*/
|
473
|
+
public void setStyleName(String style) {
|
474
|
+
resetStyleName(getStyleElement(), style);
|
475
|
+
}
|
476
|
+
|
477
|
+
/**
|
478
|
+
* Sets the title associated with this object. The title is the 'tool-tip'
|
479
|
+
* displayed to users when they hover over the object.
|
480
|
+
*
|
481
|
+
* @param title the object's new title
|
482
|
+
*/
|
483
|
+
public void setTitle(String title) {
|
484
|
+
if (title == null || title.length() == 0) {
|
485
|
+
DOM.removeElementAttribute(element, "title");
|
486
|
+
} else {
|
487
|
+
DOM.setElementAttribute(element, "title", title);
|
488
|
+
}
|
489
|
+
}
|
490
|
+
|
491
|
+
/**
|
492
|
+
* Sets whether this object is visible.
|
493
|
+
*
|
494
|
+
* @param visible <code>true</code> to show the object, <code>false</code>
|
495
|
+
* to hide it
|
496
|
+
*/
|
497
|
+
public void setVisible(boolean visible) {
|
498
|
+
setVisible(element, visible);
|
499
|
+
}
|
500
|
+
|
501
|
+
/**
|
502
|
+
* Sets the object's width. This width does not include decorations such as
|
503
|
+
* border, margin, and padding.
|
504
|
+
*
|
505
|
+
* @param width the object's new width, in CSS units (e.g. "10px", "1em")
|
506
|
+
*/
|
507
|
+
public void setWidth(String width) {
|
508
|
+
// This exists to deal with an inconsistency in IE's implementation where
|
509
|
+
// it won't accept negative numbers in length measurements
|
510
|
+
assert extractLengthValue(width.trim().toLowerCase()) >= 0 :
|
511
|
+
"CSS widths should not be negative";
|
512
|
+
DOM.setStyleAttribute(element, "width", width);
|
513
|
+
}
|
514
|
+
|
515
|
+
/**
|
516
|
+
* Adds a set of events to be sunk by this object. Note that only
|
517
|
+
* {@link Widget widgets} may actually receive events, but can receive events
|
518
|
+
* from all objects contained within them.
|
519
|
+
*
|
520
|
+
* @param eventBitsToAdd a bitfield representing the set of events to be added
|
521
|
+
* to this element's event set
|
522
|
+
* @see com.google.gwt.user.client.Event
|
523
|
+
*/
|
524
|
+
public void sinkEvents(int eventBitsToAdd) {
|
525
|
+
DOM.sinkEvents(getElement(), eventBitsToAdd
|
526
|
+
| DOM.getEventsSunk(getElement()));
|
527
|
+
}
|
528
|
+
|
529
|
+
/**
|
530
|
+
* This method is overridden so that any object can be viewed in the debugger
|
531
|
+
* as an HTML snippet.
|
532
|
+
*
|
533
|
+
* @return a string representation of the object
|
534
|
+
*/
|
535
|
+
public String toString() {
|
536
|
+
if (element == null) {
|
537
|
+
return "(null handle)";
|
538
|
+
}
|
539
|
+
return DOM.toString(element);
|
540
|
+
}
|
541
|
+
|
542
|
+
/**
|
543
|
+
* Removes a set of events from this object's event list.
|
544
|
+
*
|
545
|
+
* @param eventBitsToRemove a bitfield representing the set of events to be
|
546
|
+
* removed from this element's event set
|
547
|
+
* @see #sinkEvents
|
548
|
+
* @see com.google.gwt.user.client.Event
|
549
|
+
*/
|
550
|
+
public void unsinkEvents(int eventBitsToRemove) {
|
551
|
+
DOM.sinkEvents(getElement(), DOM.getEventsSunk(getElement())
|
552
|
+
& (~eventBitsToRemove));
|
553
|
+
}
|
554
|
+
|
555
|
+
/**
|
556
|
+
* Template method that returns the element to which style names will be
|
557
|
+
* applied. By default it returns the root element, but this method may be
|
558
|
+
* overridden to apply styles to a child element.
|
559
|
+
*
|
560
|
+
* @return the element to which style names will be applied
|
561
|
+
*/
|
562
|
+
protected Element getStyleElement() {
|
563
|
+
return element;
|
564
|
+
}
|
565
|
+
|
566
|
+
/**
|
567
|
+
* Sets this object's browser element. UIObject subclasses must call this
|
568
|
+
* method before attempting to call any other methods.
|
569
|
+
*
|
570
|
+
* If the browser element has already been set, then the current element's
|
571
|
+
* position is located in the DOM and removed. The new element is added into
|
572
|
+
* the previous element's position.
|
573
|
+
*
|
574
|
+
* @param elem the object's new element
|
575
|
+
*/
|
576
|
+
protected void setElement(Element elem) {
|
577
|
+
if (this.element != null) {
|
578
|
+
// replace this.element in its parent with elem.
|
579
|
+
replaceNode(this.element, elem);
|
580
|
+
}
|
581
|
+
|
582
|
+
this.element = elem;
|
583
|
+
|
584
|
+
// We do not actually force the creation of a primary style name here.
|
585
|
+
// Instead, we do it lazily -- when it is aboslutely required --
|
586
|
+
// in getStyleName(), addStyleName(), and removeStyleName().
|
587
|
+
}
|
588
|
+
|
589
|
+
/**
|
590
|
+
* Intended to be used to pull the value out of a CSS length. We rely on the
|
591
|
+
* behavior of parseFloat to ignore non-numeric chars in its input. If the
|
592
|
+
* value is "auto" or "inherit", 0 will be returned.
|
593
|
+
*
|
594
|
+
* @param s The CSS length string to extract
|
595
|
+
* @return The leading numeric portion of <code>s</code>, or 0 if "auto" or
|
596
|
+
* "inherit" are passed in.
|
597
|
+
*/
|
598
|
+
private native double extractLengthValue(String s) /*-{
|
599
|
+
if (s == "auto" || s == "inherit" || s == "") {
|
600
|
+
return 0;
|
601
|
+
} else {
|
602
|
+
return parseFloat(s);
|
603
|
+
}
|
604
|
+
}-*/;
|
605
|
+
|
606
|
+
private native void replaceNode(Element node, Element newNode) /*-{
|
607
|
+
var p = node.parentNode;
|
608
|
+
if (!p) {
|
609
|
+
return;
|
610
|
+
}
|
611
|
+
p.insertBefore(newNode, node);
|
612
|
+
p.removeChild(node);
|
613
|
+
}-*/;
|
614
|
+
}
|