View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.codemirror;
23  
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.List;
27  
28  import javax.el.MethodExpression;
29  import javax.faces.application.ResourceDependency;
30  import javax.faces.component.behavior.ClientBehaviorHolder;
31  import javax.faces.context.FacesContext;
32  import javax.faces.event.FacesEvent;
33  
34  import org.primefaces.component.api.AbstractPrimeHtmlInputTextArea;
35  import org.primefaces.component.api.Widget;
36  import org.primefaces.extensions.event.CompleteEvent;
37  import org.primefaces.util.LangUtils;
38  
39  /**
40   * Component class for the <code>CodeMirror</code> component.
41   *
42   * @author Thomas Andraschko / last modified by $Author$
43   * @version $Revision$
44   * @since 0.3
45   */
46  @ResourceDependency(library = "primefaces", name = "jquery/jquery.js")
47  @ResourceDependency(library = "primefaces", name = "jquery/jquery-plugins.js")
48  @ResourceDependency(library = "primefaces", name = "core.js")
49  @ResourceDependency(library = "primefaces-extensions", name = "primefaces-extensions.js")
50  @ResourceDependency(library = "primefaces-extensions", name = "codemirror/codemirror.js")
51  @ResourceDependency(library = "primefaces-extensions", name = "codemirror/codemirror.css")
52  public class CodeMirror extends AbstractPrimeHtmlInputTextArea implements ClientBehaviorHolder, Widget {
53  
54      public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.CodeMirror";
55      public static final String COMPONENT_FAMILY = "org.primefaces.extensions.component";
56      public static final String EVENT_HIGHLIGHT_COMPLETE = "highlightComplete";
57      private static final String DEFAULT_RENDERER = "org.primefaces.extensions.component.CodeMirrorRenderer";
58  
59      private static final List<String> UNOBSTRUSIVE_EVENT_NAMES = LangUtils.unmodifiableList(EVENT_HIGHLIGHT_COMPLETE);
60      private static final Collection<String> EVENT_NAMES = LangUtils.concat(AbstractPrimeHtmlInputTextArea.EVENT_NAMES, UNOBSTRUSIVE_EVENT_NAMES);
61  
62      private List<String> suggestions = null;
63  
64      /**
65       * Properties that are tracked by state saving.
66       *
67       * @author Thomas Andraschko / last modified by $Author$
68       * @version $Revision$
69       */
70      @SuppressWarnings("java:S115")
71      protected enum PropertyKeys {
72  
73          //@formatter:off
74          widgetVar,
75          theme,
76          mode,
77          indentUnit,
78          smartIndent,
79          tabSize,
80          indentWithTabs,
81          electricChars,
82          keyMap,
83          lineWrapping,
84          lineNumbers,
85          firstLineNumber,
86          gutter,
87          fixedGutter,
88          readonly,
89          matchBrackets,
90          workTime,
91          workDelay,
92          pollInterval,
93          undoDepth,
94          tabindex,
95          extraKeys,
96          completeMethod,
97          process,
98          onstart,
99          oncomplete,
100         onerror,
101         onsuccess,
102         global,
103         async,
104         escape,
105         escapeSuggestions
106         //@formatter:on
107     }
108 
109     public CodeMirror() {
110         setRendererType(DEFAULT_RENDERER);
111     }
112 
113     @Override
114     public Collection<String> getEventNames() {
115         return EVENT_NAMES;
116     }
117 
118     @Override
119     public String getFamily() {
120         return COMPONENT_FAMILY;
121     }
122 
123     public String getTheme() {
124         return (String) getStateHelper().eval(PropertyKeys.theme, null);
125     }
126 
127     public void setTheme(final String theme) {
128         getStateHelper().put(PropertyKeys.theme, theme);
129     }
130 
131     public String getMode() {
132         return (String) getStateHelper().eval(PropertyKeys.mode, null);
133     }
134 
135     public void setMode(final String mode) {
136         getStateHelper().put(PropertyKeys.mode, mode);
137     }
138 
139     public String getKeyMap() {
140         return (String) getStateHelper().eval(PropertyKeys.keyMap, null);
141     }
142 
143     public void setKeyMap(final String keyMap) {
144         getStateHelper().put(PropertyKeys.keyMap, keyMap);
145     }
146 
147     public String getWidgetVar() {
148         return (String) getStateHelper().eval(PropertyKeys.widgetVar, null);
149     }
150 
151     public void setWidgetVar(final String widgetVar) {
152         getStateHelper().put(PropertyKeys.widgetVar, widgetVar);
153     }
154 
155     public Integer getIndentUnit() {
156         return (Integer) getStateHelper().eval(PropertyKeys.indentUnit, null);
157     }
158 
159     public void setIndentUnit(final Integer indentUnit) {
160         getStateHelper().put(PropertyKeys.indentUnit, indentUnit);
161     }
162 
163     public Integer getTabSize() {
164         return (Integer) getStateHelper().eval(PropertyKeys.tabSize, null);
165     }
166 
167     public void setFirstLineNumber(final Integer firstLineNumber) {
168         getStateHelper().put(PropertyKeys.firstLineNumber, firstLineNumber);
169     }
170 
171     public Integer getFirstLineNumber() {
172         return (Integer) getStateHelper().eval(PropertyKeys.firstLineNumber, null);
173     }
174 
175     public void setTabSize(final Integer tabSize) {
176         getStateHelper().put(PropertyKeys.tabSize, tabSize);
177     }
178 
179     public Boolean isLineNumbers() {
180         return (Boolean) getStateHelper().eval(PropertyKeys.lineNumbers, null);
181     }
182 
183     public void setLineNumbers(final Boolean lineNumbers) {
184         getStateHelper().put(PropertyKeys.lineNumbers, lineNumbers);
185     }
186 
187     public Boolean isSmartIndent() {
188         return (Boolean) getStateHelper().eval(PropertyKeys.smartIndent, null);
189     }
190 
191     public void setSmartIndent(final Boolean smartIndent) {
192         getStateHelper().put(PropertyKeys.smartIndent, smartIndent);
193     }
194 
195     @Override
196     public boolean isReadonly() {
197         return (Boolean) getStateHelper().eval(PropertyKeys.readonly, false);
198     }
199 
200     @Override
201     public void setReadonly(final boolean readonly) {
202         getStateHelper().put(PropertyKeys.readonly, readonly);
203     }
204 
205     public Boolean isIndentWithTabs() {
206         return (Boolean) getStateHelper().eval(PropertyKeys.indentWithTabs, null);
207     }
208 
209     public void setIndentWithTabs(final Boolean indentWithTabs) {
210         getStateHelper().put(PropertyKeys.indentWithTabs, indentWithTabs);
211     }
212 
213     public Boolean isElectricChars() {
214         return (Boolean) getStateHelper().eval(PropertyKeys.electricChars, null);
215     }
216 
217     public void setElectricChars(final Boolean electricChars) {
218         getStateHelper().put(PropertyKeys.electricChars, electricChars);
219     }
220 
221     public Boolean isLineWrapping() {
222         return (Boolean) getStateHelper().eval(PropertyKeys.lineWrapping, null);
223     }
224 
225     public void setLineWrapping(final Boolean lineWrapping) {
226         getStateHelper().put(PropertyKeys.lineWrapping, lineWrapping);
227     }
228 
229     public Boolean isGutter() {
230         return (Boolean) getStateHelper().eval(PropertyKeys.gutter, null);
231     }
232 
233     public void setGutter(final Boolean gutter) {
234         getStateHelper().put(PropertyKeys.gutter, gutter);
235     }
236 
237     public Boolean isFixedGutter() {
238         return (Boolean) getStateHelper().eval(PropertyKeys.fixedGutter, null);
239     }
240 
241     public void setFixedGutter(final Boolean fixedGutter) {
242         getStateHelper().put(PropertyKeys.fixedGutter, fixedGutter);
243     }
244 
245     public Boolean isMatchBrackets() {
246         return (Boolean) getStateHelper().eval(PropertyKeys.matchBrackets, null);
247     }
248 
249     public void setMatchBrackets(final Boolean matchBrackets) {
250         getStateHelper().put(PropertyKeys.matchBrackets, matchBrackets);
251     }
252 
253     public Integer getWorkTime() {
254         return (Integer) getStateHelper().eval(PropertyKeys.workTime, null);
255     }
256 
257     public void setWorkTime(final Integer workTime) {
258         getStateHelper().put(PropertyKeys.workTime, workTime);
259     }
260 
261     public Integer getWorkDelay() {
262         return (Integer) getStateHelper().eval(PropertyKeys.workDelay, null);
263     }
264 
265     public void setWorkDelay(final Integer workDelay) {
266         getStateHelper().put(PropertyKeys.workDelay, workDelay);
267     }
268 
269     public Integer getPollInterval() {
270         return (Integer) getStateHelper().eval(PropertyKeys.pollInterval, null);
271     }
272 
273     public void setPollInterval(final Integer pollInterval) {
274         getStateHelper().put(PropertyKeys.pollInterval, pollInterval);
275     }
276 
277     public Integer getUndoDepth() {
278         return (Integer) getStateHelper().eval(PropertyKeys.undoDepth, null);
279     }
280 
281     public void setUndoDepth(final Integer undoDepth) {
282         getStateHelper().put(PropertyKeys.undoDepth, undoDepth);
283     }
284 
285     @Override
286     public String getTabindex() {
287         return (String) getStateHelper().eval(PropertyKeys.tabindex, null);
288     }
289 
290     @Override
291     public void setTabindex(final String tabindex) {
292         getStateHelper().put(PropertyKeys.tabindex, tabindex);
293     }
294 
295     public String getExtraKeys() {
296         return (String) getStateHelper().eval(PropertyKeys.extraKeys, null);
297     }
298 
299     public void setExtraKeys(final String extraKeys) {
300         getStateHelper().put(PropertyKeys.extraKeys, extraKeys);
301     }
302 
303     public MethodExpression getCompleteMethod() {
304         return (MethodExpression) getStateHelper().eval(PropertyKeys.completeMethod, null);
305     }
306 
307     public void setCompleteMethod(final MethodExpression completeMethod) {
308         getStateHelper().put(PropertyKeys.completeMethod, completeMethod);
309     }
310 
311     public String getProcess() {
312         return (String) getStateHelper().eval(PropertyKeys.process, null);
313     }
314 
315     public void setProcess(final String process) {
316         getStateHelper().put(PropertyKeys.process, process);
317     }
318 
319     public String getOnstart() {
320         return (String) getStateHelper().eval(PropertyKeys.onstart, null);
321     }
322 
323     public void setOnstart(final String onstart) {
324         getStateHelper().put(PropertyKeys.onstart, onstart);
325     }
326 
327     public String getOncomplete() {
328         return (String) getStateHelper().eval(PropertyKeys.oncomplete, null);
329     }
330 
331     public void setOncomplete(final String oncomplete) {
332         getStateHelper().put(PropertyKeys.oncomplete, oncomplete);
333     }
334 
335     public String getOnerror() {
336         return (String) getStateHelper().eval(PropertyKeys.onerror, null);
337     }
338 
339     public void setOnerror(final String onerror) {
340         getStateHelper().put(PropertyKeys.onerror, onerror);
341     }
342 
343     public String getOnsuccess() {
344         return (String) getStateHelper().eval(PropertyKeys.onsuccess, null);
345     }
346 
347     public void setOnsuccess(final String onsuccess) {
348         getStateHelper().put(PropertyKeys.onsuccess, onsuccess);
349     }
350 
351     public boolean isGlobal() {
352         return (Boolean) getStateHelper().eval(PropertyKeys.global, true);
353     }
354 
355     public void setGlobal(final boolean global) {
356         getStateHelper().put(PropertyKeys.global, global);
357     }
358 
359     public boolean isAsync() {
360         return (Boolean) getStateHelper().eval(PropertyKeys.async, false);
361     }
362 
363     public void setAsync(final boolean async) {
364         getStateHelper().put(PropertyKeys.async, async);
365     }
366 
367     public boolean isEscape() {
368         return (Boolean) getStateHelper().eval(PropertyKeys.escape, true);
369     }
370 
371     public void setEscape(final boolean escape) {
372         getStateHelper().put(PropertyKeys.escape, escape);
373     }
374 
375     public boolean isEscapeSuggestions() {
376         return (Boolean) getStateHelper().eval(PropertyKeys.escapeSuggestions, true);
377     }
378 
379     public void setEscapeSuggestions(final boolean suggestions) {
380         getStateHelper().put(PropertyKeys.escapeSuggestions, suggestions);
381     }
382 
383     @Override
384     public void broadcast(final FacesEvent event) {
385         super.broadcast(event);
386 
387         final FacesContext facesContext = FacesContext.getCurrentInstance();
388         final MethodExpression completeMethod = getCompleteMethod();
389 
390         if (completeMethod != null && event instanceof CompleteEvent) {
391             suggestions = (List<String>) completeMethod.invoke(
392                         facesContext.getELContext(),
393                         new Object[] {event});
394 
395             if (suggestions == null) {
396                 suggestions = new ArrayList<>();
397             }
398 
399             facesContext.renderResponse();
400         }
401     }
402 
403     public List<String> getSuggestions() {
404         return suggestions;
405     }
406 
407     @Override
408     public Object saveState(FacesContext context) {
409         // reset component for MyFaces view pooling
410         suggestions = null;
411 
412         return super.saveState(context);
413     }
414 }