ApplicationFactory.groovy
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.idapplicationWindow.name = attributes.id
064             if (attributes.nameapplicationWindow.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 (!windowreturn 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 != propertythrow 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 }