001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.options.indentation;
043:
044: import java.lang.reflect.Method;
045: import java.util.Collection;
046: import java.util.HashSet;
047: import java.util.Iterator;
048: import java.util.Set;
049: import org.netbeans.api.editor.mimelookup.MimeLookup;
050: import org.netbeans.api.editor.mimelookup.MimePath;
051: import org.netbeans.modules.editor.options.BaseOptions;
052: import org.netbeans.modules.editor.settings.storage.api.EditorSettings;
053:
054: import org.openide.text.IndentEngine;
055: import org.openide.util.Lookup;
056:
057: class IndentationModel {
058:
059: private boolean originalExpandedTabs;
060: private int originalSpacesPerTab = 0;
061: private int originalTabSize = 0;
062: private int originalRightMargin = 0;
063:
064: private boolean changed = false;
065:
066: IndentationModel() {
067: // save original values
068: originalExpandedTabs = isExpandTabs();
069: originalSpacesPerTab = getSpacesPerTab().intValue();
070: originalTabSize = getTabSize().intValue();
071: originalRightMargin = getRightMargin().intValue();
072: }
073:
074: boolean isExpandTabs() {
075: return ((Boolean) getParameter("isExpandTabs", Boolean.FALSE))
076: .booleanValue();
077: }
078:
079: void setExpandTabs(boolean expand) {
080: setParameter("setExpandTabs", Boolean.valueOf(expand),
081: Boolean.TYPE);
082: updateChanged();
083: }
084:
085: Integer getSpacesPerTab() {
086: return (Integer) getParameter("getSpacesPerTab", new Integer(4));
087: }
088:
089: void setSpacesPerTab(Integer spaces) {
090: if (spaces.intValue() > 0)
091: setParameter("setSpacesPerTab", spaces, Integer.TYPE);
092: updateChanged();
093: }
094:
095: Integer getTabSize() {
096: BaseOptions options = getExampleBaseOptions();
097: if (options != null) {
098: return options.getTabSize();
099: } else {
100: return 4;
101: }
102: }
103:
104: void setTabSize(Integer size) {
105: if (size.intValue() > 0) {
106: BaseOptions options = getExampleBaseOptions();
107: if (options != null) {
108: options.setTabSize(size);
109: }
110: }
111: updateChanged();
112: }
113:
114: Integer getRightMargin() {
115: BaseOptions options = getExampleBaseOptions();
116: if (options != null) {
117: return options.getTextLimitWidth();
118: } else {
119: return 120;
120: }
121: }
122:
123: void setRightMargin(Integer margin) {
124: if (margin.intValue() > 0) {
125: BaseOptions options = getExampleBaseOptions();
126: if (options != null) {
127: options.setTextLimitWidth(margin);
128: }
129: }
130: updateChanged();
131: }
132:
133: boolean isChanged() {
134: return changed;
135: }
136:
137: void applyChanges() {
138: if (!changed)
139: return; // no changes
140: applyParameterToAll("setExpandTabs", Boolean
141: .valueOf(isExpandTabs()), Boolean.TYPE); //NOI18N
142: applyParameterToAll("setSpacesPerTab", getSpacesPerTab(),
143: Integer.TYPE); //NOI18N
144: applyParameterToAll("setTabSize", getTabSize(), Integer.TYPE); //NOI18N
145: applyParameterToAll("setTextLimitWidth", getRightMargin(),
146: Integer.TYPE); //NOI18N
147: }
148:
149: void revertChanges() {
150: if (!changed)
151: return; // no changes
152: if (isExpandTabs() != originalExpandedTabs) {
153: setExpandTabs(originalExpandedTabs);
154: }
155: if (getSpacesPerTab().intValue() != originalSpacesPerTab
156: && originalSpacesPerTab > 0) {
157: setSpacesPerTab(new Integer(originalSpacesPerTab));
158: }
159: if (getTabSize().intValue() != originalTabSize
160: && originalTabSize > 0) {
161: setTabSize(new Integer(originalTabSize));
162: }
163: if (getRightMargin().intValue() != originalRightMargin
164: && originalRightMargin > 0) {
165: setRightMargin(new Integer(originalRightMargin));
166: }
167: }
168:
169: // private helper methods ..................................................
170:
171: private void updateChanged() {
172: changed = isExpandTabs() != originalExpandedTabs
173: || getSpacesPerTab().intValue() != originalSpacesPerTab
174: || getTabSize().intValue() != originalTabSize
175: || getRightMargin().intValue() != originalRightMargin;
176: }
177:
178: private BaseOptions exampleBaseOptions = null;
179: private IndentEngine exampleIndentEngine = null;
180:
181: private BaseOptions getExampleBaseOptions() {
182: if (exampleBaseOptions == null) {
183: BaseOptions options = MimeLookup.getLookup(
184: MimePath.parse("text/xml")).lookup(
185: BaseOptions.class); //NOI18N
186: if (options == null) {
187: options = MimeLookup.getLookup(
188: MimePath.parse("text/plain")).lookup(
189: BaseOptions.class); //NOI18N
190: }
191: exampleBaseOptions = options;
192: }
193: return exampleBaseOptions;
194: }
195:
196: private IndentEngine getExampleIndentEngine() {
197: if (exampleIndentEngine == null) {
198: BaseOptions options = getExampleBaseOptions();
199: exampleIndentEngine = options == null ? null : options
200: .getIndentEngine();
201: }
202: return exampleIndentEngine;
203: }
204:
205: private Object getParameter(String parameterName,
206: Object defaultValue) {
207: IndentEngine eng = getExampleIndentEngine();
208: if (eng != null) {
209: try {
210: Method method = eng.getClass().getMethod(parameterName,
211: new Class[0]);
212: return method.invoke(eng, new Object[0]);
213: } catch (Exception ex) {
214: }
215: }
216: return defaultValue;
217: }
218:
219: private void setParameter(String parameterName,
220: Object parameterValue, Class parameterType) {
221: IndentEngine eng = getExampleIndentEngine();
222: if (eng != null) {
223: try {
224: Method method = eng.getClass().getMethod(parameterName,
225: new Class[] { parameterType });
226: method.invoke(eng, new Object[] { parameterValue });
227: } catch (Exception ex) {
228: }
229: }
230: }
231:
232: private void applyParameterToAll(String parameterName,
233: Object parameterValue, Class parameterType) {
234: HashSet<IndentEngine> mimeTypeBoundEngines = new HashSet<IndentEngine>();
235: Set<String> mimeTypes = EditorSettings.getDefault()
236: .getMimeTypes();
237: for (String mimeType : mimeTypes) {
238: BaseOptions baseOptions = MimeLookup.getLookup(
239: MimePath.parse(mimeType)).lookup(BaseOptions.class);
240:
241: if (baseOptions == null) {
242: continue;
243: }
244:
245: IndentEngine indentEngine = baseOptions.getIndentEngine();
246: mimeTypeBoundEngines.add(indentEngine);
247:
248: ClassLoader classLoader = Lookup.getDefault().lookup(
249: ClassLoader.class);
250: // XXX: HACK
251: if (baseOptions
252: .getClass()
253: .getName()
254: .equals(
255: "org.netbeans.modules.java.editor.options.JavaOptions")
256: && //NOI18N
257: !indentEngine
258: .getClass()
259: .getName()
260: .equals(
261: "org.netbeans.modules.editor.java.JavaIndentEngine")) //NOI18N
262: {
263: try {
264: Class javaIndentEngineClass = classLoader
265: .loadClass("org.netbeans.modules.editor.java.JavaIndentEngine"); //NOI18N
266: indentEngine = (IndentEngine) Lookup.getDefault()
267: .lookup(javaIndentEngineClass);
268: baseOptions.setIndentEngine(indentEngine);
269: } catch (Exception ex) {
270: }
271: }
272: if (baseOptions.getClass().getName().equals(
273: "org.netbeans.modules.web.core.syntax.JSPOptions")
274: && //NOI18N
275: !indentEngine
276: .getClass()
277: .getName()
278: .equals(
279: "org.netbeans.modules.web.core.syntax.JspIndentEngine")) //NOI18N
280: {
281: try {
282: Class jspIndentEngineClass = classLoader
283: .loadClass("org.netbeans.modules.web.core.syntax.JspIndentEngine"); //NOI18N
284: indentEngine = (IndentEngine) Lookup.getDefault()
285: .lookup(jspIndentEngineClass);
286: baseOptions.setIndentEngine(indentEngine);
287: } catch (Exception ex) {
288: }
289: }
290:
291: // update BaseOptions
292: try {
293: Method method = baseOptions.getClass().getMethod(
294: parameterName, new Class[] { parameterType });
295: method.invoke(baseOptions,
296: new Object[] { parameterValue });
297: } catch (Exception ex) {
298: // ignore
299: }
300:
301: // update IndentEngine
302: try {
303: Method method = indentEngine.getClass().getMethod(
304: parameterName, new Class[] { parameterType });
305: method.invoke(indentEngine,
306: new Object[] { parameterValue });
307: } catch (Exception ex) {
308: // ignore
309: }
310: }
311:
312: // There can be other engines that are not currently hooked up with
313: // BaseOptions/mime-type.
314:
315: Collection allEngines = Lookup.getDefault().lookupAll(
316: IndentEngine.class);
317: for (Iterator it = allEngines.iterator(); it.hasNext();) {
318: IndentEngine indentEngine = (IndentEngine) it.next();
319: if (!mimeTypeBoundEngines.contains(indentEngine)) {
320: try {
321: Method method = indentEngine.getClass().getMethod(
322: parameterName,
323: new Class[] { parameterType });
324: method.invoke(indentEngine,
325: new Object[] { parameterValue });
326: } catch (Exception e) {
327: // ignore
328: }
329: }
330: }
331: }
332:
333: }
|