ApplicationFactory.groovy
001 /*
002  * Copyright 2008-2016 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.idapplicationWindow.name = attributes.id
062             if (attributes.nameapplicationWindow.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 (!windowreturn 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 != propertythrow 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 }