001 /*
002 * Copyright 2008-2015 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.builder.swing.factory
017
018 import org.codehaus.groovy.runtime.InvokerHelper
019
020 import javax.swing.JApplet
021 import javax.swing.JButton
022 import javax.swing.JMenuBar
023 import javax.swing.JToolBar
024 import javax.swing.SwingUtilities
025 import java.awt.Component
026 import java.awt.Window
027
028 /**
029 * Created by IntelliJ IDEA.
030 * @author Danno.Ferrin
031 * Date: Sep 4, 2008
032 * Time: 8:52:40 PM
033 */
034 @SuppressWarnings("rawtypes")
035 class ApplicationFactory extends AbstractFactory {
036 static final String DELEGATE_PROPERTY_DEFAULT_BUTTON = "_delegateProperty:defaultButton";
037 static final String DEFAULT_DELEGATE_PROPERTY_DEFAULT_BUTTON = "defaultButton";
038
039 static final String DELEGATE_PROPERTY_CANCEL_BUTTON = "_delegateProperty:cancelButton";
040 static final String DEFAULT_DELEGATE_PROPERTY_CANCEL_BUTTON = "cancelButton";
041
042 static boolean swingXPresent
043 static Class<?> jxStatusBarClass
044 static {
045 try {
046 ClassLoader cl = getClass().getClassLoader();
047 if (cl) {
048 jxStatusBarClass = cl.loadClass('org.jdesktop.swingx.JXStatusBar')
049 } else {
050 jxStatusBarClass = Class.forName('org.jdesktop.swingx.JXStatusBar', true, ApplicationFactory.classLoader)
051 }
052 swingXPresent = true
053 } catch (Throwable t) {
054 swingXPresent = false
055 }
056 }
057
058 Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) {
059 def applicationWindow = builder.application.createApplicationContainer([:])
060 if (applicationWindow instanceof Window) {
061 if (attributes.id) applicationWindow.name = attributes.id
062 if (attributes.name) applicationWindow.name = attributes.name
063 builder.application.windowManager.attach(applicationWindow.name, applicationWindow)
064 }
065 def window = getContainingWindow(applicationWindow)
066
067 if (applicationWindow instanceof JApplet && swingXPresent) {
068 // bake in some JXFrame stuff if present
069 applicationWindow.rootPane = getClass().getClassLoader().loadClass('org.jdesktop.swingx.JXRootPane').newInstance()
070 }
071
072 if (!window) return applicationWindow
073
074 if (swingXPresent) {
075 builder.context[DELEGATE_PROPERTY_CANCEL_BUTTON] = attributes.remove("cancelButtonProperty") ?: DEFAULT_DELEGATE_PROPERTY_CANCEL_BUTTON
076
077 builder.context.cancelButtonDelegate =
078 builder.addAttributeDelegate { myBuilder, node, myAttributes ->
079 if (myAttributes.cancelButton && (node instanceof JButton)) {
080 applicationWindow.rootPaneExt.cancelButton = node
081 myAttributes.remove('cancelButton')
082 }
083 }
084 }
085
086 builder.context.pack = attributes.remove('pack')
087 builder.context.show = attributes.remove('show')
088 builder.addDisposalClosure(applicationWindow.&dispose)
089 builder.containingWindows.add(window)
090
091 /*
092 if(attributes.containsKey('hideBeforeHandler') && builder.app instanceof SwingGriffonApplication) {
093 builder.applicationWindow.windowManager.hideBeforeHandler = attributes.remove('hideBeforeHandler')
094 }
095 */
096
097 builder.context[DELEGATE_PROPERTY_DEFAULT_BUTTON] = attributes.remove("defaultButtonProperty") ?: DEFAULT_DELEGATE_PROPERTY_DEFAULT_BUTTON
098 builder.context.defaultButtonDelegate =
099 builder.addAttributeDelegate { myBuilder, node, myAttributes ->
100 if ((node instanceof JButton) && (builder.containingWindows[-1] == window)) {
101 // in Java 6 use descending iterator
102 ListIterator li = builder.contexts.listIterator();
103 Map context
104 while (li.hasNext()) context = li.next()
105 while (context && context[FactoryBuilderSupport.CURRENT_NODE] != window) {
106 context = li.previous()
107 }
108 def defaultButtonProperty = context[DELEGATE_PROPERTY_DEFAULT_BUTTON] ?: DEFAULT_DELEGATE_PROPERTY_DEFAULT_BUTTON
109 def defaultButton = myAttributes.remove(defaultButtonProperty)
110 if (defaultButton) {
111 applicationWindow.rootPane.defaultButton = node
112 }
113 }
114 }
115
116 return applicationWindow
117 }
118
119 boolean onHandleNodeAttributes(FactoryBuilderSupport builder, Object node, Map attributes) {
120 for (Map.Entry entry : (Set<Map.Entry>) attributes.entrySet()) {
121 String property = entry.getKey().toString();
122 Object value = entry.getValue();
123 // be forgiving on attributes, so an applet can set an icon without punishment, etc
124 try {
125 InvokerHelper.setProperty(node, property, value);
126 } catch (MissingPropertyException mpe) {
127 if (mpe.property != property) throw mpe
128 }
129 }
130 return false
131 }
132
133 void handleRootPaneExtTasks(FactoryBuilderSupport builder, Window container, Map attributes) {
134 container.rootPaneExt.cancelButton = null
135 container.rootPaneExt.defaultButton = null
136 builder.context.cancelButtonDelegate =
137 builder.addAttributeDelegate { myBuilder, node, myAttributes ->
138 if (myAttributes.cancelButton && (node instanceof JButton)) {
139 container.rootPaneExt.cancelButton = node
140 myAttributes.remove('cancelButton')
141 }
142 }
143
144 super.handleRootPaneTasks(builder, container, attributes)
145 }
146
147 void onNodeCompleted(FactoryBuilderSupport builder, Object parent, Object node) {
148 def window = getContainingWindow(node)
149 builder.removeAttributeDelegate(builder.context.cancelButtonDelegate)
150 if (window instanceof Window) {
151 def containingWindows = builder.containingWindows
152 if (!containingWindows.empty && containingWindows.last == window) {
153 containingWindows.removeLast()
154 }
155
156 // can't pack or show an applet...
157
158 if (builder.context.pack) {
159 window.pack()
160 }
161 if (builder.context.show) {
162 window.visible = true
163 }
164 }
165
166 builder.removeAttributeDelegate(builder.context.defaultButtonDelegate)
167 }
168
169 private getContainingWindow(node) {
170 if (node instanceof JApplet || node instanceof Window) {
171 return node
172 } else if (node instanceof Component) {
173 return SwingUtilities.getWindowAncestor(node)
174 }
175 return null
176 }
177
178 void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
179 if (!(child instanceof Component) || (child instanceof Window)) {
180 return;
181 }
182 if (child instanceof JMenuBar) {
183 parent.JMenuBar = child
184 } else if (swingXPresent && (child instanceof JToolBar)) {
185 parent.rootPane.toolBar = child
186 } else if (swingXPresent && (jxStatusBarClass.isAssignableFrom(child.getClass()))) {
187 parent.rootPane.statusBar = child
188 } else {
189 try {
190 def constraints = builder.context.constraints
191 if (constraints != null) {
192 parent.contentPane.add(child, constraints)
193 } else {
194 parent.contentPane.add(child)
195 }
196 } catch (MissingPropertyException mpe) {
197 parent.contentPane.add(child)
198 }
199 }
200 }
201 }
|