View Javadoc
1   /**
2    * 
3    * Copyright (c) 2013-2014, Openflexo
4    * Copyright (c) 2011-2012, AgileBirds
5    * 
6    * This file is part of Gina-swing-editor, a component of the software infrastructure 
7    * developed at Openflexo.
8    * 
9    * 
10   * Openflexo is dual-licensed under the European Union Public License (EUPL, either 
11   * version 1.1 of the License, or any later version ), which is available at 
12   * https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
13   * and the GNU General Public License (GPL, either version 3 of the License, or any 
14   * later version), which is available at http://www.gnu.org/licenses/gpl.html .
15   * 
16   * You can redistribute it and/or modify under the terms of either of these licenses
17   * 
18   * If you choose to redistribute it and/or modify under the terms of the GNU GPL, you
19   * must include the following additional permission.
20   *
21   *          Additional permission under GNU GPL version 3 section 7
22   *
23   *          If you modify this Program, or any covered work, by linking or 
24   *          combining it with software containing parts covered by the terms 
25   *          of EPL 1.0, the licensors of this Program grant you additional permission
26   *          to convey the resulting work. * 
27   * 
28   * This software is distributed in the hope that it will be useful, but WITHOUT ANY 
29   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
30   * PARTICULAR PURPOSE. 
31   *
32   * See http://www.openflexo.org/license.html for details.
33   * 
34   * 
35   * Please contact Openflexo (openflexo-contacts@openflexo.org)
36   * or visit www.openflexo.org if you need additional information.
37   * 
38   */
39  
40  package org.openflexo.gina.swing.editor.controller.action;
41  
42  import java.io.File;
43  import java.util.logging.Logger;
44  
45  import javax.swing.JFrame;
46  
47  import org.openflexo.connie.BindingFactory;
48  import org.openflexo.connie.BindingModel;
49  import org.openflexo.connie.DataBinding;
50  import org.openflexo.connie.DataBinding.BindingDefinitionType;
51  import org.openflexo.connie.DefaultBindable;
52  import org.openflexo.connie.type.TypeUtils;
53  import org.openflexo.gina.controller.FIBController.Status;
54  import org.openflexo.gina.model.FIBComponent;
55  import org.openflexo.gina.model.FIBContainer;
56  import org.openflexo.gina.model.FIBModelFactory;
57  import org.openflexo.gina.model.FIBModelObject;
58  import org.openflexo.gina.model.container.FIBPanel;
59  import org.openflexo.gina.model.container.FIBPanel.FlowLayoutAlignment;
60  import org.openflexo.gina.model.container.FIBPanel.Layout;
61  import org.openflexo.gina.model.container.layout.TwoColsLayoutConstraints;
62  import org.openflexo.gina.model.container.layout.TwoColsLayoutConstraints.TwoColsLayoutLocation;
63  import org.openflexo.gina.model.widget.FIBButton;
64  import org.openflexo.gina.model.widget.FIBCustom;
65  import org.openflexo.gina.model.widget.FIBFile;
66  import org.openflexo.gina.model.widget.FIBFile.FileMode;
67  import org.openflexo.gina.model.widget.FIBLabel;
68  import org.openflexo.gina.model.widget.FIBLabel.Align;
69  import org.openflexo.gina.model.widget.FIBReferencedComponent;
70  import org.openflexo.gina.swing.editor.controller.FIBEditorController;
71  import org.openflexo.gina.swing.editor.controller.FIBEditorIconLibrary;
72  import org.openflexo.gina.swing.utils.BindingSelector;
73  import org.openflexo.gina.swing.utils.JFIBDialog;
74  import org.openflexo.gina.swing.utils.JFIBPreferences;
75  import org.openflexo.icon.IconFactory;
76  import org.openflexo.logging.FlexoLogger;
77  import org.openflexo.pamela.exceptions.ModelDefinitionException;
78  import org.openflexo.rm.FileResourceImpl;
79  import org.openflexo.toolbox.StringUtils;
80  
81  public class MakeReusableComponent extends AbstractEditorActionImpl {
82  
83  	private static final Logger logger = FlexoLogger.getLogger(MakeReusableComponent.class.getPackage().getName());
84  
85  	public MakeReusableComponent(FIBEditorController anEditorController, JFrame frame) {
86  		super("make_reusable_component", IconFactory.getImageIcon(FIBEditorIconLibrary.PANEL_ICON, FIBEditorIconLibrary.DUPLICATE),
87  				anEditorController, frame);
88  	}
89  
90  	@Override
91  	public boolean isEnabledFor(FIBModelObject object) {
92  		return object instanceof FIBContainer;
93  	}
94  
95  	@Override
96  	public boolean isVisibleFor(FIBModelObject object) {
97  		return true;
98  	}
99  
100 	@Override
101 	public FIBModelObject performAction(FIBModelObject object) {
102 		if (object instanceof FIBContainer) {
103 			FIBContainer component = (FIBContainer) object;
104 			FIBContainer parent = component.getParent();
105 			return makeReusableComponent(component, parent, getFrame());
106 		}
107 		return null;
108 	}
109 
110 	public FIBModelObject makeReusableComponent(FIBContainer component, FIBContainer parent, JFrame frame) {
111 		FIBModelFactory dialogFactory = null;
112 		try {
113 			dialogFactory = new FIBModelFactory(null);
114 		} catch (ModelDefinitionException e) {
115 			e.printStackTrace();
116 			return null;
117 		}
118 		MakeReusableComponentParameters params = new MakeReusableComponentParameters(component, parent);
119 		FIBPanel panel = dialogFactory.newFIBPanel();
120 		panel.setDataClass(params.getClass());
121 		panel.setLayout(Layout.twocols);
122 		FIBLabel title = dialogFactory.newFIBLabel("Make reusable component");
123 		title.setAlign(Align.center);
124 		panel.addToSubComponents(title, new TwoColsLayoutConstraints(TwoColsLayoutLocation.center, true, false));
125 		panel.addToSubComponents(dialogFactory.newFIBLabel("file"), new TwoColsLayoutConstraints(TwoColsLayoutLocation.left, false, false));
126 		FIBFile fileWidget = dialogFactory.newFIBFile();
127 		fileWidget.setMode(FileMode.SaveMode);
128 		fileWidget.setData(new DataBinding<>("data.reusableComponentFile"));
129 		panel.addToSubComponents(fileWidget, new TwoColsLayoutConstraints(TwoColsLayoutLocation.right, true, false));
130 		panel.addToSubComponents(dialogFactory.newFIBLabel("data"), new TwoColsLayoutConstraints(TwoColsLayoutLocation.left, false, false));
131 		FIBCustom dataWidget = dialogFactory.newFIBCustom();
132 		dataWidget.setComponentClass(BindingSelector.class);
133 		dataWidget.setData(new DataBinding<>("data.data"));
134 		FIBCustom.FIBCustomAssignment assignment = dialogFactory.newInstance(FIBCustom.FIBCustomAssignment.class);
135 		assignment.setOwner(dataWidget);
136 		assignment.setVariable(new DataBinding<>("component.bindable"));
137 		assignment.setValue(new DataBinding<>("data"));
138 		assignment.setMandatory(true);
139 		;
140 		dataWidget.addToAssignments(assignment);
141 		panel.addToSubComponents(dataWidget, new TwoColsLayoutConstraints(TwoColsLayoutLocation.right, true, false));
142 		FIBPanel controlPanel = dialogFactory.newFIBPanel();
143 		controlPanel.setLayout(Layout.flow);
144 		controlPanel.setFlowAlignment(FlowLayoutAlignment.CENTER);
145 		FIBButton validateButton = dialogFactory.newFIBButton();
146 		validateButton.setLabel("validate");
147 		validateButton.setAction(new DataBinding<>("controller.validateAndDispose()"));
148 		controlPanel.addToSubComponents(validateButton);
149 		FIBButton cancelButton = dialogFactory.newFIBButton();
150 		cancelButton.setLabel("cancel");
151 		cancelButton.setAction(new DataBinding<>("controller.cancelAndDispose()"));
152 		controlPanel.addToSubComponents(cancelButton);
153 		panel.addToSubComponents(controlPanel, new TwoColsLayoutConstraints(TwoColsLayoutLocation.center, true, false));
154 
155 		JFIBDialog<?> dialog = JFIBDialog.instanciateAndShowDialog(panel, params, frame, true);
156 
157 		if (dialog.getStatus() == Status.VALIDATED) {
158 			if (params.reusableComponentFile != null) {
159 				logger.info("Saving new component to " + params.reusableComponentFile);
160 				FIBContainer reusableComponent = component;
161 				parent.removeFromSubComponents(reusableComponent);
162 				reusableComponent.setControllerClass(parent.getRootComponent().getControllerClass());
163 				reusableComponent.setDataClass(TypeUtils.getBaseClass(params.data.getAnalyzedType()));
164 				for (FIBComponent child : reusableComponent.getAllSubComponents()) {
165 					for (DataBinding<?> binding : child.getDeclaredBindings()) {
166 						if (binding.isSet()) {
167 							if (binding.toString().startsWith(params.data.toString())) {
168 								binding.setUnparsedBinding(binding.toString().replace(params.data.toString(), "data"));
169 							}
170 							if (StringUtils.isNotEmpty(reusableComponent.getName())) {
171 								if (binding.toString().startsWith(reusableComponent.getName() + ".")) {
172 									binding.setUnparsedBinding(binding.toString().substring(reusableComponent.getName().length() + 1));
173 								}
174 							}
175 						}
176 					}
177 				}
178 				DataBinding<Boolean> visible = reusableComponent.getVisible();
179 				reusableComponent.setData(null);
180 				reusableComponent.setVisible(null);
181 
182 				try {
183 					FileResourceImpl reusableComponentResource = new FileResourceImpl(params.reusableComponentFile);
184 					logger.info("Save to " + reusableComponentResource);
185 					reusableComponent.getFIBLibrary().save(reusableComponent, reusableComponentResource);
186 					// logger.info("Current directory = " + editorController.getEditor().getEditedComponentFile().getParentFile());
187 					// RelativePathFileConverter relativePathFileConverter = new RelativePathFileConverter(editorController.getEditor()
188 					// .getEditedComponentFile().getParentFile());
189 					// String relativeFilePath = relativePathFileConverter.convertToString(params.reusableComponentFile);
190 					// logger.info("Relative file path: " + relativeFilePath);
191 					FIBReferencedComponent widget = dialogFactory.newFIBReferencedComponent();
192 					widget.setComponentFile(reusableComponentResource);
193 					widget.setData(params.data);
194 					widget.setVisible(visible);
195 					parent.addToSubComponents(widget, reusableComponent.getConstraints());
196 					return widget;
197 				} catch (Exception e) {
198 					logger.severe("Unable to create FileResourceLocation from File: " + params.reusableComponentFile.getName());
199 					e.printStackTrace();
200 				}
201 
202 			}
203 		}
204 
205 		return null;
206 	}
207 
208 	public static class MakeReusableComponentParameters extends DefaultBindable {
209 		public String componentName;
210 		public File reusableComponentFile;
211 		public Class<?> reusableComponentClass;
212 		public DataBinding<Object> data;
213 
214 		private final FIBComponent contextComponent;
215 
216 		public MakeReusableComponentParameters(FIBContainer component, FIBContainer parent) {
217 			this.contextComponent = parent;
218 			if (StringUtils.isNotEmpty(component.getName())) {
219 				componentName = component.getName();
220 				reusableComponentFile = new File(JFIBPreferences.getLastDirectory(), componentName + ".fib");
221 			}
222 			else {
223 				reusableComponentFile = new File(JFIBPreferences.getLastDirectory(), "ReusableComponent.fib");
224 			}
225 			if (component.getData().isSet()) {
226 				data = new DataBinding<>(component.getData().toString(), this, Object.class, BindingDefinitionType.GET);
227 			}
228 			else {
229 				data = new DataBinding<>(this, Object.class, BindingDefinitionType.GET);
230 			}
231 		}
232 
233 		@Override
234 		public BindingModel getBindingModel() {
235 			return contextComponent.getBindingModel();
236 		}
237 
238 		@Override
239 		public BindingFactory getBindingFactory() {
240 			return contextComponent.getBindingFactory();
241 		}
242 
243 		@Override
244 		public void notifiedBindingChanged(DataBinding<?> dataBinding) {
245 			reusableComponentClass = TypeUtils.getBaseClass(data.getAnalyzedType());
246 			System.out.println("reusableComponentClass=" + reusableComponentClass);
247 		}
248 
249 		@Override
250 		public void notifiedBindingDecoded(DataBinding<?> dataBinding) {
251 			reusableComponentClass = TypeUtils.getBaseClass(data.getAnalyzedType());
252 			System.out.println("reusableComponentClass=" + reusableComponentClass);
253 		}
254 	}
255 
256 }