View Javadoc
1   /*
2    * Tethys: GUI Utilities
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.tethys.swing.control;
18  
19  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
20  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
21  import io.github.tonywasher.joceanus.tethys.core.control.TethysUICoreHTMLManager;
22  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
23  import io.github.tonywasher.joceanus.tethys.swing.base.TethysUISwingNode;
24  
25  import javax.swing.JEditorPane;
26  import javax.swing.event.HyperlinkEvent;
27  import javax.swing.event.HyperlinkListener;
28  import javax.swing.text.html.HTMLDocument;
29  import javax.swing.text.html.HTMLEditorKit;
30  import javax.swing.text.html.HTMLFrameHyperlinkEvent;
31  import javax.swing.text.html.StyleSheet;
32  import java.awt.print.PrinterAbortException;
33  import java.awt.print.PrinterException;
34  import java.io.IOException;
35  import java.net.URL;
36  
37  /**
38   * Swing HTML Manager.
39   */
40  public class TethysUISwingHTMLManager
41          extends TethysUICoreHTMLManager {
42      /**
43       * The logger.
44       */
45      private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(TethysUISwingHTMLManager.class);
46  
47      /**
48       * The stream close error.
49       */
50      private static final String ERROR_STREAM = "Failed to close stream";
51  
52      /**
53       * The Node.
54       */
55      private final TethysUISwingNode theNode;
56  
57      /**
58       * EditorPane.
59       */
60      private final JEditorPane theEditor;
61  
62      /**
63       * Base StyleSheet.
64       */
65      private final StyleSheet theBaseStyleSheet;
66  
67      /**
68       * Modifications StyleSheet.
69       */
70      private StyleSheet theModifiedStyleSheet;
71  
72      /**
73       * Constructor.
74       *
75       * @param pFactory the GUI Factory
76       */
77      TethysUISwingHTMLManager(final TethysUICoreFactory<?> pFactory) {
78          /* Initialise underlying class */
79          super(pFactory);
80  
81          /* Create EditorPane */
82          theEditor = new JEditorPane();
83          theEditor.setEditable(false);
84          theEditor.setContentType("text/html");
85  
86          /* Add an editor kit to the editor */
87          final HTMLEditorKit myEditorKit = new HTMLEditorKit();
88          theEditor.setEditorKit(myEditorKit);
89  
90          /* Create the document for the window */
91          final HTMLDocument myDoc = (HTMLDocument) myEditorKit.createDefaultDocument();
92          theEditor.setDocument(myDoc);
93  
94          /* Obtain the base styleSheet */
95          theBaseStyleSheet = myDoc.getStyleSheet();
96  
97          /* Add hyperLink listener */
98          theEditor.addHyperlinkListener(new HTMLListener());
99  
100         /* Create the node */
101         theNode = new TethysUISwingNode(theEditor);
102     }
103 
104     @Override
105     public TethysUISwingNode getNode() {
106         return theNode;
107     }
108 
109     @Override
110     public void setVisible(final boolean pVisible) {
111         theEditor.setVisible(pVisible);
112     }
113 
114     @Override
115     public void setEnabled(final boolean pEnabled) {
116         theEditor.setEnabled(pEnabled);
117     }
118 
119     @Override
120     public void setPreferredWidth(final Integer pWidth) {
121         theNode.setPreferredWidth(pWidth);
122     }
123 
124     @Override
125     public void setPreferredHeight(final Integer pHeight) {
126         theNode.setPreferredHeight(pHeight);
127     }
128 
129     @Override
130     protected void loadHTMLContent(final String pHTMLString) {
131         /* Set the help text */
132         theEditor.setText(pHTMLString);
133         theEditor.setCaretPosition(0);
134         theEditor.requestFocusInWindow();
135     }
136 
137     @Override
138     protected void loadCSSContents() {
139         /* If there is already a styleSheet */
140         if (theModifiedStyleSheet != null) {
141             /* Remove it */
142             theBaseStyleSheet.removeStyleSheet(theModifiedStyleSheet);
143             theModifiedStyleSheet = null;
144         }
145 
146         /* If we have any additional rules */
147         final String myCSS = getProcessedCSS();
148         if (myCSS != null) {
149             /* Create the styleSheet */
150             theModifiedStyleSheet = new StyleSheet();
151             theModifiedStyleSheet.addRule(myCSS);
152 
153             /* Load into the editor */
154             theBaseStyleSheet.addStyleSheet(theModifiedStyleSheet);
155         }
156     }
157 
158     @Override
159     public void scrollToReference(final String pReference) {
160         /* Execute the function call */
161         theEditor.scrollToReference(pReference);
162     }
163 
164     @Override
165     public void printIt() {
166         /* Print the current report */
167         try {
168             /* Print the data */
169             theEditor.print();
170 
171         } catch (PrinterAbortException ignore) {
172             /* Ignore exception and just return */
173         } catch (PrinterException e) {
174             LOGGER.error("Failed to print", e);
175         }
176     }
177 
178     /**
179      * Handle HyperLink.
180      *
181      * @param pEvent the event
182      */
183     void handleFrameHyperLinkEvent(final HTMLFrameHyperlinkEvent pEvent) {
184         final HTMLDocument doc = (HTMLDocument) theEditor.getDocument();
185         doc.processHTMLFrameHyperlinkEvent(pEvent);
186     }
187 
188     /**
189      * Handle HyperLink.
190      *
191      * @param pEvent the event
192      */
193     void handleHyperLinkEvent(final HyperlinkEvent pEvent) {
194         final URL url = pEvent.getURL();
195         try {
196             final String myDesc = pEvent.getDescription();
197             if (url == null) {
198                 /* display the new page */
199                 processReference(myDesc);
200             } else {
201                 theEditor.setPage(url);
202             }
203         } catch (IOException t) {
204             LOGGER.error(ERROR_STREAM, t);
205         }
206     }
207 
208     /**
209      * HyperLinkListener.
210      */
211     private final class HTMLListener
212             implements HyperlinkListener {
213         @Override
214         public void hyperlinkUpdate(final HyperlinkEvent e) {
215             /* Ignore non-activated events */
216             if (!e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
217                 return;
218             }
219             /* If this is a Frame hyperLink event */
220             if (e instanceof HTMLFrameHyperlinkEvent myEvent) {
221                 handleFrameHyperLinkEvent(myEvent);
222 
223                 /* else look for a URL */
224             } else {
225                 handleHyperLinkEvent(e);
226             }
227         }
228     }
229 }