/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.designer.core.editor.styles.styleeditor;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.JXTaskPaneContainer;
import org.pentaho.reporting.designer.core.ReportDesignerBoot;
import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.editor.styles.Messages;
import org.pentaho.reporting.designer.core.editor.styles.SimpleStyleEditorPanel;
import org.pentaho.reporting.designer.core.util.IconLoader;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleSheet;
import org.pentaho.reporting.engine.classic.core.style.css.CSSParseException;
import org.pentaho.reporting.engine.classic.core.style.css.ElementStyleDefinition;
import org.pentaho.reporting.engine.classic.core.style.css.ElementStyleRule;
import org.pentaho.reporting.engine.classic.core.style.css.StyleSheetParserUtil;
import org.pentaho.reporting.engine.classic.core.style.css.namespaces.NamespaceCollection;
import org.pentaho.reporting.engine.classic.core.style.css.selector.CSSSelector;
import org.pentaho.reporting.libraries.designtime.swing.CommonDialog;
import org.pentaho.reporting.libraries.designtime.swing.LibSwingUtil;
import org.pentaho.reporting.libraries.designtime.swing.event.DocumentChangeHandler;
import org.w3c.css.sac.SelectorList;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
public class StyleDefinitionEditorDialog extends CommonDialog {
private class SelectorUpdateHandler extends DocumentChangeHandler {
private JTextField textField;
private ElementStyleRule styleRule;
private JXTaskPane pane;
private Color color;
private Color errorColor;
private SelectorUpdateHandler( final JTextField textField,
final ElementStyleRule styleRule,
final JXTaskPane pane ) {
this.textField = textField;
this.styleRule = styleRule;
this.pane = pane;
this.color = textField.getBackground();
this.errorColor = new Color( 1f, 0.75f, 0.75f );
}
protected void handleChange( final DocumentEvent e ) {
try {
final NamespaceCollection nc = StyleSheetParserUtil.getInstance().getNamespaceCollection();
final String selectorText = textField.getText();
final SelectorList list = StyleSheetParserUtil.getInstance().parseSelector( nc, selectorText );
styleRule.clearSelectors();
textField.setBackground( color );
for ( int i = 0; i < list.getLength(); i++ ) {
final CSSSelector selector = (CSSSelector) list.item( i );
styleRule.addSelector( selector );
}
pane.setTitle( Messages.getString( "StyleDefinitionEditorDialog.RuleTitle", selectorText ) );
} catch ( CSSParseException e1 ) {
textField.setBackground( errorColor );
}
}
}
private class CloseAction extends AbstractAction {
private CloseAction() {
putValue( Action.NAME, Messages.getString( "StyleDefinitionEditorDialog.Close.Text" ) );
putValue( Action.SHORT_DESCRIPTION, Messages.getString( "StyleDefinitionEditorDialog.Close.Description" ) );
putValue( Action.MNEMONIC_KEY, Messages.getOptionalMnemonic( "StyleDefinitionEditorDialog.Close.Mnemonic" ) );
putValue( Action.ACCELERATOR_KEY,
Messages.getOptionalKeyStroke( "StyleDefinitionEditorDialog.Close.Accelerator" ) );
putValue( Action.SMALL_ICON, IconLoader.getInstance().getEmptyIcon() );
}
public void actionPerformed( final ActionEvent e ) {
getCancelAction().actionPerformed( e );
}
}
private class ElementStyleDefinitionChangeHandler implements ElementStyleDefinitionChangeListener {
private ElementStyleDefinitionChangeHandler() {
}
public void styleRuleAdded( final ElementStyleDefinitionChangeEvent event ) {
addRulePane( event.getStyleRule() );
}
public void styleRuleRemoved( final ElementStyleDefinitionChangeEvent event ) {
removeRulePane( event.getStyleRule() );
}
public void styleRulesChanged( final ElementStyleDefinitionChangeEvent event ) {
rebuildPanes();
}
}
private class FileSourceChangeHandler implements PropertyChangeListener {
private FileSourceChangeHandler() {
}
public void propertyChange( final PropertyChangeEvent evt ) {
if ( editorContext.getSource() == null ) {
setTitle( Messages.getString( "StyleDefinitionEditorDialog.Title" ) );
} else {
setTitle( Messages.getString( "StyleDefinitionEditorDialog.TitleFile", editorContext.getSource() ) );
}
}
}
private JXTaskPaneContainer taskPaneContainer;
private HashMap<ElementStyleRule, JXTaskPane> taskPanes;
private JXTaskPane taskPane;
private boolean standalone;
private JMenuBar standaloneMenuBar;
private JMenuBar inlineMenuBar;
private StyleDefinitionEditorContext editorContext;
public StyleDefinitionEditorDialog( final ReportDesignerContext designerContext ) {
init( designerContext );
}
public StyleDefinitionEditorDialog( final Frame owner,
final ReportDesignerContext designerContext ) throws HeadlessException {
super( owner );
init( designerContext );
}
public StyleDefinitionEditorDialog( final Dialog owner,
final ReportDesignerContext designerContext ) throws HeadlessException {
super( owner );
init( designerContext );
}
protected void init( final ReportDesignerContext designerContext ) {
this.taskPanes = new HashMap<ElementStyleRule, JXTaskPane>();
this.editorContext = new StyleDefinitionEditorContext( designerContext, this, new ElementStyleDefinition() );
this.editorContext.addPropertyChangeListener( "source", new FileSourceChangeHandler() );
setTitle( Messages.getString( "StyleDefinitionEditorDialog.InlineTitle" ) );
final JMenu fileMenu = new JMenu( Messages.getString( "StyleDefinitionEditorDialog.Menu.File.Label" ) );
fileMenu.setMnemonic( Messages.getMnemonic( "StyleDefinitionEditorDialog.Menu.File.Mnemonic" ) );
fileMenu.add( new OpenAction( editorContext ) );
fileMenu.add( new SaveAction( editorContext ) );
fileMenu.add( new SaveAsAction( editorContext ) );
fileMenu.addSeparator();
fileMenu.add( new CloseAction() );
standaloneMenuBar = new JMenuBar();
standaloneMenuBar.add( fileMenu );
final JMenu inlineMenu = new JMenu( Messages.getString( "StyleDefinitionEditorDialog.Menu.File.Label" ) );
inlineMenu.setMnemonic( Messages.getMnemonic( "StyleDefinitionEditorDialog.Menu.File.Mnemonic" ) );
inlineMenu.add( new OpenAction( editorContext ) );
inlineMenu.add( new SaveAction( editorContext ) );
inlineMenu.add( new SaveAsAction( editorContext ) );
inlineMenuBar = new JMenuBar();
inlineMenuBar.add( inlineMenu );
setJMenuBar( inlineMenuBar );
super.init();
editorContext.addElementStyleDefinitionChangeListener( new ElementStyleDefinitionChangeHandler() );
}
protected void performInitialResize() {
setSize( 800, 600 );
LibSwingUtil.centerDialogInParent( this );
}
protected String getDialogId() {
return "ReportDesigner.Core.StyleDefinitionEditor";
}
public boolean isStandalone() {
return standalone;
}
public void setStandalone( final boolean standalone ) {
this.standalone = standalone;
if ( standalone ) {
setJMenuBar( standaloneMenuBar );
setButtonPaneVisible( false );
setTitle( Messages.getString( "StyleDefinitionEditorDialog.Title" ) );
} else {
setJMenuBar( inlineMenuBar );
setButtonPaneVisible( true );
setTitle( Messages.getString( "StyleDefinitionEditorDialog.InlineTitle" ) );
}
}
protected Component createContentPane() {
taskPane = new JXTaskPane();
taskPane.setSpecial( true );
taskPane.setCollapsed( false );
taskPane.setTitle( Messages.getString( "StyleDefinitionEditorDialog.TaskTitle" ) );
taskPane.add( new AddStyleRuleAction( editorContext ) );
taskPaneContainer = new JXTaskPaneContainer();
taskPaneContainer.add( taskPane );
return new JScrollPane( taskPaneContainer );
}
private void rebuildPanes() {
this.taskPanes.clear();
this.taskPaneContainer.removeAll();
this.taskPaneContainer.add( taskPane );
final ElementStyleDefinition existing = editorContext.getStyleDefinition();
for ( int i = 0; i < existing.getRuleCount(); i += 1 ) {
final ElementStyleSheet maybeRule = existing.getRule( i );
if ( maybeRule instanceof ElementStyleRule == false ) {
continue;
}
final ElementStyleRule rule = (ElementStyleRule) maybeRule;
addRulePane( rule );
}
}
private void addRulePane( final ElementStyleRule rule ) {
final String selectorText = convertSelectorText( rule );
final JTextField selector = new JTextField();
selector.setText( selectorText );
final JXTaskPane pane = new JXTaskPane();
pane.setTitle( Messages.getString( "StyleDefinitionEditorDialog.RuleTitle", selectorText ) );
pane.add( new RemoveStyleRuleAction( editorContext, rule ) );
pane.add( selector );
final SimpleStyleEditorPanel comp = new SimpleStyleEditorPanel( editorContext );
comp.setReportDesignerContext( editorContext.getDesignerContext() );
comp.setData( rule );
pane.add( comp );
selector.getDocument().addDocumentListener( new SelectorUpdateHandler( selector, rule, pane ) );
taskPanes.put( rule, pane );
taskPaneContainer.add( pane );
taskPaneContainer.revalidate();
taskPaneContainer.repaint();
}
private void removeRulePane( final ElementStyleRule rule ) {
final JXTaskPane jxTaskPane = taskPanes.get( rule );
if ( jxTaskPane != null ) {
this.taskPaneContainer.remove( jxTaskPane );
this.taskPanes.remove( rule );
this.taskPaneContainer.revalidate();
this.taskPaneContainer.repaint();
}
}
private String convertSelectorText( final ElementStyleRule rule ) {
final NamespaceCollection nc = StyleSheetParserUtil.getInstance().getNamespaceCollection();
final StringBuilder b = new StringBuilder();
for ( int i = 0; i < rule.getSelectorCount(); i += 1 ) {
if ( i != 0 ) {
b.append( ", " );
}
final CSSSelector selector = rule.getSelector( i );
b.append( selector.print( nc ) );
}
return b.toString();
}
public ElementStyleDefinition performEdit( final ElementStyleDefinition existing ) {
editorContext.setStyleDefinition( existing );
if ( super.performEdit() == false ) {
return existing;
}
return editorContext.getStyleDefinition().clone();
}
public static StyleDefinitionEditorDialog createDialog( final Component parent,
final ReportDesignerContext context ) {
final StyleDefinitionEditorDialog exceptionDialog;
final Window window = LibSwingUtil.getWindowAncestor( parent );
if ( window instanceof Dialog ) {
exceptionDialog = new StyleDefinitionEditorDialog( (Dialog) window, context );
} else if ( window instanceof Frame ) {
exceptionDialog = new StyleDefinitionEditorDialog( (Frame) window, context );
} else {
exceptionDialog = new StyleDefinitionEditorDialog( context );
}
return exceptionDialog;
}
public static void main( final String[] args ) {
ClassicEngineBoot.getInstance().start();
ReportDesignerBoot.getInstance().start();
final StyleDefinitionEditorDialog dialog = new StyleDefinitionEditorDialog( null );
dialog.setStandalone( true );
dialog.setVisible( true );
}
}