//$HeadURL$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2008 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.igeo.views.swing; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLFrameHyperlinkEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.views.HelpManager; /** * * * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ public class HelpFrame extends JFrame { private static final long serialVersionUID = -963193689947547993L; private static final ILogger LOG = LoggerFactory.getLogger( HelpFrame.class ); private JSplitPane jSplitPane1; private JEditorPane helpArea; private JPanel pnKeyword; private JTabbedPane jTabbedPane1; private JTree tree; private HelpManager helpManager; private ApplicationContainer<Container> appContainer; private static HelpFrame helpFrame; /** * * @param helpManager */ @SuppressWarnings("unchecked") private HelpFrame( HelpManager helpManager ) { this.helpManager = helpManager; this.appContainer = (ApplicationContainer<Container>) helpManager.getApplicationContainer(); initGUI(); } /** * * @param appContainer * @param helpManager * @return singleton instance of HelpFrame */ public static HelpFrame getInstance( HelpManager helpManager ) { if ( helpFrame == null ) { helpManager.init(); helpFrame = new HelpFrame( helpManager ); } return helpFrame; } /** * resets help frame so next invocation of {@link #getInstance(HelpManager)} will load help pages again */ public static void reset() { helpFrame = null; } private void initGUI() { try { BorderLayout thisLayout = new BorderLayout(); setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ); getContentPane().setLayout( thisLayout ); { jSplitPane1 = new JSplitPane(); getContentPane().add( jSplitPane1, BorderLayout.CENTER ); jSplitPane1.setDividerLocation( 200 ); { JScrollPane sc = new JScrollPane(); sc.getHorizontalScrollBar().setAutoscrolls( true ); sc.getVerticalScrollBar().setAutoscrolls( true ); sc.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); jSplitPane1.add( sc, JSplitPane.RIGHT ); { helpArea = new JEditorPane(); helpArea.setEditable( false ); // load initial/default page String page = helpManager.getProjectDefaultHelpPage(); if ( page == null ) { page = "./help/igeodesktop_main.en.html"; } helpArea.setPage( appContainer.resolve( page ) ); sc.setViewportView( helpArea ); helpArea.addHyperlinkListener( new Hyperactive() ); } } { jTabbedPane1 = new JTabbedPane(); jSplitPane1.add( jTabbedPane1, JSplitPane.LEFT ); jTabbedPane1.setMinimumSize( new java.awt.Dimension( 200, 5 ) ); jTabbedPane1.setSize( 200, 517 ); jTabbedPane1.setPreferredSize( new java.awt.Dimension( 131, 517 ) ); jTabbedPane1.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); { JScrollPane sc = new JScrollPane( tree = new JTree() ); sc.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); JPanel p = new JPanel( new BorderLayout() ); p.add( sc, BorderLayout.CENTER ); jTabbedPane1.addTab( "modules", null, p, null ); } { JScrollPane sc = new JScrollPane(); sc.getHorizontalScrollBar().setAutoscrolls( true ); sc.getVerticalScrollBar().setAutoscrolls( true ); sc.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); pnKeyword = new JPanel(); sc.setViewportView( pnKeyword ); BoxLayout keywordPanelLayout = new BoxLayout( pnKeyword, javax.swing.BoxLayout.Y_AXIS ); pnKeyword.setLayout( keywordPanelLayout ); pnKeyword.setBackground( Color.WHITE ); jTabbedPane1.addTab( "keywords", null, sc, null ); } } } fillKeywordPanel(); fillModulePanel(); this.setBounds( 100, 100, 900, 600 ); this.setPreferredSize( new Dimension( 800, 600 ) ); SwingUtilities.updateComponentTreeUI( this ); } catch ( Exception e ) { e.printStackTrace(); } } /** * for each keyword a button will be added to a pane/list that enables accessing/loading the HTML page a keyword is * assigend to. For this an {@link ActionListener} will be invoked that is responsible for loading a HTML page into * the help area on the right * */ private void fillKeywordPanel() { Set<String> keywords = helpManager.getKeywords(); String[] array = keywords.toArray( new String[keywords.size()] ); Arrays.sort( array ); Color bgColor = pnKeyword.getBackground(); KeywordActionListener listener = new KeywordActionListener(); for ( String keyword : array ) { JButton label = new JButton( "- " + keyword ); label.setBorder( BorderFactory.createEmptyBorder( 2, 5, 1, 10 ) ); label.setBorderPainted( false ); label.setRolloverEnabled( true ); label.setBackground( bgColor ); label.setForeground( Color.BLACK ); label.addActionListener( listener ); label.setActionCommand( keyword ); pnKeyword.add( label ); } } /** * for each module a button will be added to a pane/list that enables accessing/loading the HTML page a keyword is * assigend to. For this an {@link ActionListener} will be invoked that is responsible for loading a HTML page into * the help area on the right * */ private void fillModulePanel() { Set<String> modules = helpManager.getModuleNames(); String[] array = modules.toArray( new String[modules.size()] ); Arrays.sort( array ); DefaultMutableTreeNode root = new DefaultMutableTreeNode( Messages.getMessage( getLocale(), "$DG10077" ) ); List<String> kw = helpManager.getKeywordsByModule( "iGeoDesktop" ); for ( String keyword : kw ) { String tmp = keyword.substring( 0, keyword.lastIndexOf( ':' ) ); DefaultMutableTreeNode child = new DefaultMutableTreeNode( tmp ); child.setUserObject( tmp ); root.add( child ); } TreeModel model = new DefaultTreeModel( root ); for ( String moduleName : array ) { DefaultMutableTreeNode child = new DefaultMutableTreeNode( moduleName ); root.add( child ); kw = helpManager.getKeywordsByModule( moduleName ); for ( String keyword : kw ) { String tmp = keyword.substring( 0, keyword.lastIndexOf( ':' ) ); DefaultMutableTreeNode subChild = new DefaultMutableTreeNode( tmp ); subChild.setUserObject( tmp ); child.add( subChild ); } } tree.addMouseListener( new ModuleActionListener() ); tree.setModel( model ); tree.expandRow( 0 ); } /** * loads help page for passed keyword. The keyword string must be qualified. This means after a keyword seperated by * ':' the name of the module a keyword is assigned too must follow; e.g. editing:Digitizer. * * @param keyword */ public void gotoKeyword( String keyword ) { try { String s = helpManager.getReferenceForKeyword( keyword ); if ( s != null ) { URL url = appContainer.resolve( s ); helpArea.setPage( url ); } } catch ( Exception e ) { e.printStackTrace(); } } /** * loads help page for passed module * * @param module */ public void gotoModule( String module ) { try { URL url = appContainer.resolve( helpManager.getReferenceForModule( module ) ); helpArea.setPage( url ); } catch ( Exception e ) { LOG.logWarning( "ignore", e ); } } // /////////////////////////////////////////////////////////////////////// // inner classes // /////////////////////////////////////////////////////////////////////// /** * * * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ private class KeywordActionListener implements ActionListener { /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed( ActionEvent event ) { JButton button = (JButton) event.getSource(); String tmp = button.getActionCommand(); gotoKeyword( tmp ); } } /** * * * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ private class ModuleActionListener extends MouseAdapter { /* * (non-Javadoc) * * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent) */ @Override public void mouseClicked( MouseEvent event ) { Point dropPoint = event.getPoint(); TreePath path = tree.getPathForLocation( dropPoint.x, dropPoint.y ); if ( path != null ) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent(); if ( parent == null ) { try { helpArea.setPage( appContainer.resolve( "./help/igeodesktop_main.en.html" ) ); } catch ( IOException e ) { LOG.logWarning( Messages.getMessage( getLocale(), "$DG10078", "./help/igeodesktop_main.en.html" ) ); } } else { String kw = (String) node.getUserObject(); String module = (String) parent.getUserObject(); String tmp = null; try { // look if node represent help for a module in general tmp = helpManager.getReferenceForModule( kw ); if ( tmp == null ) { // if not it possibly is a keyword assigend to a specific page tmp = helpManager.getReferenceForKeyword( kw + ':' + module ); } if ( tmp == null ) { // and if not a keyword specific page it should be a page directly // assigend to a project tmp = helpManager.getReferenceForKeyword( kw + ":iGeoDesktop" ); } URL url = appContainer.resolve( tmp ); helpArea.setPage( url ); } catch ( IOException e ) { LOG.logWarning( Messages.getMessage( getLocale(), "$DG10078", tmp ) ); } } } } } /** * inner class for handling events forced by clicking on a link * * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ private class Hyperactive implements HyperlinkListener { public void hyperlinkUpdate( HyperlinkEvent e ) { if ( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) { JEditorPane pane = (JEditorPane) e.getSource(); if ( e instanceof HTMLFrameHyperlinkEvent ) { HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; HTMLDocument doc = (HTMLDocument) pane.getDocument(); doc.processHTMLFrameHyperlinkEvent( evt ); } else { URL url = null; try { HTMLDocument html = (HTMLDocument) e.getSourceElement().getDocument(); url = html.getBase(); url = new URL( url, e.getURL().toExternalForm() ); helpArea.setPage( url ); } catch ( Throwable t ) { LOG.logWarning( Messages.getMessage( getLocale(), "$DG10079", url ) ); } } } } } }