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