/* * Copyright 2003-2011 Tufts University Licensed under the * Educational Community License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ package tufts.vue; import tufts.vue.gui.*; import tufts.vue.gui.formattingpalette.AlignmentDropDown; import java.awt.*; import java.awt.event.*; import java.awt.font.TextAttribute; import java.util.*; import java.beans.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.text.AttributeSet; import javax.swing.text.Element; import javax.swing.text.MutableAttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.Style; import javax.swing.text.StyledEditorKit; import javax.swing.text.html.CSS; import javax.swing.text.html.HTML; import javax.swing.text.html.StyleSheet; import com.lightdev.app.shtm.SHTMLDocument; import com.lightdev.app.shtm.SHTMLEditorKitActions; import com.lightdev.app.shtm.SHTMLPanelImpl; import com.lightdev.app.shtm.Util; /** * This creates a font editor panel for editing fonts in the UI * * @version $Revision: 1.89 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $ * */ public class FontEditorPanel extends JPanel implements CaretListener, ComponentListener //,ActiveListener //implements LWEditor // implements ActionListener, VueConstants//, PropertyChangeListener//implements PropertyChangeListener { private boolean DEBUG_FONTPANEL=false; private static String[] sFontSizes; /** the font list **/ static String[] sFontNames = null; public final static String SIZE_FIELD_NAME ="richFontSizeEditor"; /** the Font selection combo box **/ public final JComboBox mFontCombo; public final JComboBox mSizeField; private final AbstractButton mBoldButton; private final AbstractButton mItalicButton; private final AbstractButton mUnderlineButton; //private final AlignmentDropDown alignmentButton; private final AbstractButton mLeftAlignButton; private final AbstractButton mCenterAlignButton; private final AbstractButton mRightAlignButton; public static ColorMenuButton mTextColorButton; private final AbstractButton orderedListButton = new VueButton("list.button.ordered"); private final AbstractButton unorderedListButton = new VueButton("list.button.unordered"); /** the property name **/ private final Object mPropertyKey; private final ButtonGroup buttonGroup = new ButtonGroup(); //plain text action listener final ActionListener styleChangeHandler; final ActionListener underlineChangeHandler; ActionListener alignmentHandler; private FontPropertyHandler fontPropertyHandler = null; //rich text actions private final SHTMLEditorKitActions.BoldAction richBoldAction = new SHTMLEditorKitActions.BoldAction(null); private final SHTMLEditorKitActions.ItalicAction richItalicAction = new SHTMLEditorKitActions.ItalicAction(null); private final SHTMLEditorKitActions.UnderlineAction richUnderlineAction = new SHTMLEditorKitActions.UnderlineAction(null); private final SHTMLEditorKitActions.ToggleListAction toggleBulletsAction = new SHTMLEditorKitActions.ToggleListAction(null,"toggleListAction",HTML.Tag.UL); private final SHTMLEditorKitActions.ToggleListAction toggleNumbersAction = new SHTMLEditorKitActions.ToggleListAction(null, "toggleNumbersAction", HTML.Tag.OL); private final SHTMLEditorKitActions.ToggleAction paraAlignLeftAction = new SHTMLEditorKitActions.ToggleAction(null, "paraAlignLeftAction",CSS.Attribute.TEXT_ALIGN, com.lightdev.app.shtm.Util.CSS_ATTRIBUTE_ALIGN_LEFT); private final SHTMLEditorKitActions.ToggleAction paraAlignCenterAction = new SHTMLEditorKitActions.ToggleAction(null, "paraAlignCenterAction",CSS.Attribute.TEXT_ALIGN, com.lightdev.app.shtm.Util.CSS_ATTRIBUTE_ALIGN_CENTER); private final SHTMLEditorKitActions.ToggleAction paraAlignRightAction = new SHTMLEditorKitActions.ToggleAction(null, "paraAlignRightAction",CSS.Attribute.TEXT_ALIGN, com.lightdev.app.shtm.Util.CSS_ATTRIBUTE_ALIGN_RIGHT); private final SHTMLEditorKitActions.FontFamilyAction fontFamilyAction = new SHTMLEditorKitActions.FontFamilyAction(null); private final SHTMLEditorKitActions.FontSizeAction fontSizeAction = new SHTMLEditorKitActions.FontSizeAction(null); private final SHTMLEditorKitActions.FontColorAction fontColorAction = new SHTMLEditorKitActions.FontColorAction(null); //private ActionListener toggleNumbersAct private ActionListener richBoldActionWrapper = null; private ActionListener richItalicActionWrapper = null; private ActionListener richUnderlineActionWrapper = null; private ActionListener toggleBulletsActionWrapper = null; private ActionListener toggleNumbersActionWrapper = null; private ActionListener paraAlignLeftActionWrapper = null; private ActionListener paraAlignCenterActionWrapper = null; private ActionListener paraAlignRightActionWrapper = null; private ActionListener fontFamilyActionWrapper = null; private ActionListener fontSizeActionWrapper = null; private LWPropertyHandler sizeHandler = null; private ActionListener globalSizeListener=null; private ActionListener globalFaceListener=null; private ActionListener globalBoldListener=null; private ActionListener globalItalicListener=null; private ActionListener globalUnderlineListener=null; private static boolean suspendItemListeners = false; private LWText lwtext = null; // dynRes.addAction(fontFamilyAction, new SHTMLEditorKitActions.FontFamilyAction(this)); // dynRes.addAction(fontSizeAction, new SHTMLEditorKitActions.FontSizeAction(this)); // dynRes.addAction(fontColorAction, new SHTMLEditorKitActions.FontColorAction(this)); public FontEditorPanel(Object propertyKey) { //super(BoxLayout.X_AXIS); setLayout(new GridBagLayout()); VUE.getFormatDock().addComponentListener(this); //ActiveInstance.addAllActiveListener(this); //VUE.addActiveListener(LWComponent.class, this); VUE.addActiveListener(RichTextBox.class, this); VUE.addActiveListener(LWComponent.class, this); // VUE.addActiveListener(LWComponent.class,this); mPropertyKey = propertyKey; setFocusable(false); //Box box = Box.createHorizontalBox(); // we set this border only to create a gap around these components // so they don't expand to 100% of the height of the region they're // in -- okay, that's not good enough -- will have to find another // way to constrain the combo-box. /* if (true) setBorder(new LineBorder(Color.pink, VertSqueeze)); else setBorder(new EmptyBorder(VertSqueeze,1,VertSqueeze,1));//t,l,b,r */ String[] sFontNames = getFontNames(); mFontCombo = new JComboBox(sFontNames); mFontCombo.setRenderer(new CustomComboBoxRenderer()); mFontCombo.setEditable(true); mFontCombo.getEditor().getEditorComponent().setFocusable(false); Font f = mFontCombo.getFont(); Font menuFont = f.deriveFont((float) 9); mFontCombo.setFont(menuFont); Component[] c =mFontCombo.getComponents(); mFontCombo.setPrototypeDisplayValue("Ludica Sans Typewriter"); // biggest font name to bother sizing to if (false) { Dimension comboSize = mFontCombo.getPreferredSize(); comboSize.height -= 2; // if too small (eg, -3), will trigger major swing layout bug mFontCombo.setMaximumSize(comboSize); } // if (GUI.isMacAqua()) // mFontCombo.setBorder(new EmptyBorder(1,0,0,0)); fontPropertyHandler = new FontPropertyHandler(mFontCombo); mFontCombo.setMaximumRowCount(30); mFontCombo.setOpaque(false); // Set selected items BEFORE adding action listeners, or during startup // we think a user has actually selected this item! mFontCombo.setSelectedItem("Arial"); mFontCombo.addActionListener(fontPropertyHandler); // We don't appear to get any events here! // mFontCombo.addItemListener(new ItemListener() { // public void itemStateChanged(ItemEvent e) { // System.err.println(mFontCombo + ": itemStateChanged " + e); // } // }); fontSizeActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; fontSizeAction.actionPerformed(e); } }; fontFamilyActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; fontFamilyAction.actionPerformed(e); } }; paraAlignRightActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; paraAlignRightAction.actionPerformed(e); } }; paraAlignLeftActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; paraAlignLeftAction.actionPerformed(e); } }; paraAlignCenterActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; paraAlignCenterAction.actionPerformed(e); } }; toggleBulletsActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; toggleBulletsAction.actionPerformed(e); } }; toggleNumbersActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; toggleNumbersAction.actionPerformed(e); } }; richBoldActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; richBoldAction.actionPerformed(e); } }; richUnderlineActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; richUnderlineAction.actionPerformed(e); } }; richItalicActionWrapper = new ActionListener(){ public void actionPerformed(ActionEvent e) { if (suspendItemListeners) return; if (EditorManager.isEditorLoading()) return; richItalicAction.actionPerformed(e); } }; /* LWText ActionListeners Start */ globalBoldListener = new ActionListener(){ public void actionPerformed(ActionEvent fe) { if (lwtext == null) return; if (EditorManager.isEditorLoading()) return; //System.out.println("BOLD : " + countf++); lwtext.richLabelBox.selectAll(); //Do Some basic set up. SimpleAttributeSet set = new SimpleAttributeSet(); SHTMLDocument srcDoc = (SHTMLDocument)lwtext.richLabelBox.getDocument(); Element charElem = srcDoc.getCharacterElement(1); AttributeSet charSet = charElem.getAttributes(); Enumeration characterAttributeEnum = charSet.getAttributeNames(); boolean isBold = false; while (characterAttributeEnum.hasMoreElements()) { Object o = characterAttributeEnum.nextElement(); if ((o.toString().equals("font-weight") && charSet.getAttribute(o).toString().equals("bold")) || o.toString().equals("b")) { isBold = true; } } String bold = !isBold ? "bold" : "normal"; //System.out.println("bold? : "+ !isBold + " ,, " + bold); Util.styleSheet().addCSSAttribute(set,CSS.Attribute.FONT_WEIGHT,bold); // set.addAttribute(HTML.Attribute.TEXT_WEIGHT, ); lwtext.richLabelBox.applyAttributes(set, false); lwtext.richLabelBox.select(0,0); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } }; globalItalicListener = new ActionListener(){ public void actionPerformed(ActionEvent fe) { if (lwtext == null) return; if (EditorManager.isEditorLoading()) return; //System.out.println("BOLD : " + countf++); lwtext.richLabelBox.selectAll(); //Do Some basic set up. SimpleAttributeSet set = new SimpleAttributeSet(); SHTMLDocument srcDoc = (SHTMLDocument)lwtext.richLabelBox.getDocument(); Element charElem = srcDoc.getCharacterElement(1); AttributeSet charSet = charElem.getAttributes(); Enumeration characterAttributeEnum = charSet.getAttributeNames(); boolean isBold = false; while (characterAttributeEnum.hasMoreElements()) { Object o = characterAttributeEnum.nextElement(); if ((o.toString().equals("font-style") && charSet.getAttribute(o).toString().equals("italic")) || o.toString().equals("i")) { isBold = true; } } String bold = !isBold ? "italic" : "normal"; //System.out.println("bold? : "+ !isBold + " ,, " + bold); Util.styleSheet().addCSSAttribute(set,CSS.Attribute.FONT_STYLE,bold); // set.addAttribute(HTML.Attribute.TEXT_WEIGHT, ); lwtext.richLabelBox.applyAttributes(set, false); lwtext.richLabelBox.select(0,0); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } }; globalUnderlineListener = new ActionListener(){ public void actionPerformed(ActionEvent fe) { if (lwtext == null) return; if (EditorManager.isEditorLoading()) return; //System.out.println("BOLD : " + countf++); lwtext.richLabelBox.selectAll(); //Do Some basic set up. SimpleAttributeSet set = new SimpleAttributeSet(); SHTMLDocument srcDoc = (SHTMLDocument)lwtext.richLabelBox.getDocument(); Element charElem = srcDoc.getCharacterElement(1); AttributeSet charSet = charElem.getAttributes(); Enumeration characterAttributeEnum = charSet.getAttributeNames(); boolean isBold = false; while (characterAttributeEnum.hasMoreElements()) { Object o = characterAttributeEnum.nextElement(); if ((o.toString().equals("text-decoration") && charSet.getAttribute(o).toString().equals("underline")) || o.toString().equals("u")) { isBold = true; } } String bold = !isBold ? "underline" : "normal"; //System.out.println("bold? : "+ !isBold + " ,, " + bold); Util.styleSheet().addCSSAttribute(set,CSS.Attribute.TEXT_DECORATION,bold); // set.addAttribute(HTML.Attribute.TEXT_WEIGHT, ); lwtext.richLabelBox.applyAttributes(set, false); lwtext.richLabelBox.select(0,0); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } }; globalSizeListener = new ActionListener(){ public void actionPerformed(ActionEvent fe) { if (suspendItemListeners) return; if (lwtext == null) return; if (EditorManager.isEditorLoading()) return; lwtext.richLabelBox.selectAll(); final String textSize = mSizeField.getSelectedItem().toString(); SHTMLDocument doc = (SHTMLDocument)lwtext.richLabelBox.getDocument(); SimpleAttributeSet set = new SimpleAttributeSet(); Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_SIZE, textSize); set.addAttribute(HTML.Attribute.SIZE, textSize); lwtext.richLabelBox.applyAttributes(set, false); lwtext.richLabelBox.select(0,0); //lwtext.setLabel0(lwtext.richLabelBox.getRichText(), false); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } }; globalFaceListener = new ActionListener(){ public void actionPerformed(ActionEvent fe) { if (suspendItemListeners) return; if (lwtext == null) return; if (EditorManager.isEditorLoading()) return; lwtext.richLabelBox.selectAll(); SHTMLDocument doc = (SHTMLDocument)lwtext.richLabelBox.getDocument(); SimpleAttributeSet set = new SimpleAttributeSet(); Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_FAMILY, mFontCombo.getSelectedItem().toString()); set.addAttribute(HTML.Attribute.FACE, mFontCombo.getSelectedItem().toString()); lwtext.richLabelBox.applyAttributes(set, false); lwtext.richLabelBox.select(0,0); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } }; /* End LWText ActionListeners */ //mFontCombo.setBorder(new javax.swing.border.LineBorder(Color.green, 2)); //mFontCombo.setBackground(Color.white); // handled by L&F tweaks in VUE.java //mFontCombo.setMaximumSize(new Dimension(50,50)); // no effect //mFontCombo.setSize(new Dimension(50,50)); // no effect //mFontCombo.setBorder(null); // already has no border //mSizeField = new NumericField( NumericField.POSITIVE_INTEGER, 2 ); if (sFontSizes == null) sFontSizes = VueResources.getStringArray("fontSizes"); mSizeField = new JComboBox(sFontSizes); //mSizeField.setModel(new FontComboBoxModel(sFontSizes)); mSizeField.setRenderer(new CustomComboBoxRenderer()); // mSizeField.setPrototypeDisplayValue("10000"); mSizeField.setEditable(true); mSizeField.setOpaque(false); mSizeField.setMaximumRowCount(30); mSizeField.setSelectedItem("13"); mSizeField.setFocusable(true); mSizeField.getEditor().getEditorComponent().setName(SIZE_FIELD_NAME); /* if (GUI.isMacAqua()) { mFontCombo.setBackground(VueTheme.getToolbarColor()); mSizeField.setBackground(VueTheme.getToolbarColor()); } else { mFontCombo.setBackground(VueTheme.getVueColor()); mSizeField.setBackground(VueTheme.getVueColor()); } */ //mSizeField.setPrototypeDisplayValue("100"); // no help in making it smaller //System.out.println("EDITOR " + mSizeField.getEditor()); //System.out.println("EDITOR-COMP " + mSizeField.getEditor().getEditorComponent()); if (mSizeField.getEditor().getEditorComponent() instanceof JTextField) { JTextField sizeEditor = (JTextField) mSizeField.getEditor().getEditorComponent(); sizeEditor.setColumns(3); // not exactly character columns } /* if (!GUI.isMacAqua()) { try { sizeEditor.setBackground(VueTheme.getTheme().getMenuBackground()); } catch (Exception e) { System.err.println("FontEditorPanel: " + e); } } */ //sizeEditor.setPreferredSize(new Dimension(20,10)); // does squat // the default size for a combo-box editor field is 9 chars // wide, and it's NOT configurable thru system L&F properties // -- it's hardcoded into Basic and Metal look and feels! God // knows what will happen on windows L&F. BTW: windows look // and feel has better combo-boxes -- they display menu // contents in sizes bigger than the top display box // (actually, both do that when they can resize), and they're // picking up more of our color override settings (and the // at-right button appears closer to Melanie's comps). // } //mSizeField.getEditor().getEditorComponent().setSize(30,10); //mSizeField.addActionListener( this); sizeHandler = new LWPropertyHandler<Integer>(LWKey.FontSize, mSizeField) { public Integer produceValue() { return new Integer(mSizeField.getSelectedItem().toString()); } public void displayValue(Integer value) { mSizeField.setSelectedItem(""+value); } }; mSizeField.addActionListener(sizeHandler); f = mSizeField.getFont(); //Font sizeFont = f.deriveFont((float) f.getSize()-2); Font sizeFont= f.deriveFont((float) 9); mSizeField.setFont( sizeFont); //mSizeField.setMaximumSize(mSizeField.getPreferredSize()); //mSizeField.setBackground(VueTheme.getVueColor()); styleChangeHandler = new LWPropertyHandler<Integer>(LWKey.FontStyle) { public Integer produceValue() { int style = Font.PLAIN; if (mItalicButton.isSelected()) style |= Font.ITALIC; if (mBoldButton.isSelected()) style |= Font.BOLD; return style; } public void displayValue(Integer value) { final int style = value; mBoldButton.setSelected((style & Font.BOLD) != 0); mItalicButton.setSelected((style & Font.ITALIC) != 0); } public void setEnabled(boolean enabled) { mBoldButton.setEnabled(enabled); mItalicButton.setEnabled(enabled); } }; underlineChangeHandler = new LWPropertyHandler<String>(LWKey.FontUnderline) { public String produceValue() { String style=""; if (mUnderlineButton.isSelected()) style="underline"; else style="normal"; return style; } public void setEnabled(boolean enabled) { mUnderlineButton.setEnabled(enabled); } public void displayValue(String propertyValue) { final String style = propertyValue; if (style.equals("underline")) mUnderlineButton.setSelected(true); else mUnderlineButton.setSelected(false); } }; mBoldButton = new VueButton.Toggle("font.button.bold",styleChangeHandler); mItalicButton = new VueButton.Toggle("font.button.italic", styleChangeHandler); mUnderlineButton = new VueButton.Toggle("font.button.underline",underlineChangeHandler); // regular components don't support this style //mUnderlineButton = new VueButton.Toggle("font.button.underline", styleChangeHandler); //alignmentButton = new AlignmentDropDown(); mLeftAlignButton = new VueButton.Toggle("list.button.leftalignment"); mCenterAlignButton = new VueButton.Toggle("list.button.centeralignment"); mRightAlignButton = new VueButton.Toggle("list.button.rightalignment"); buttonGroup.add(mLeftAlignButton); buttonGroup.add(mCenterAlignButton); buttonGroup.add(mRightAlignButton); // We can set these once -- they're not property based: mUnderlineButton.addActionListener(richUnderlineActionWrapper); orderedListButton.addActionListener(toggleNumbersActionWrapper); unorderedListButton.addActionListener(toggleBulletsActionWrapper); alignmentHandler = new LWPropertyHandler<LWComponent.Alignment>(LWKey.Alignment) { public LWComponent.Alignment produceValue() { if (mLeftAlignButton.isSelected()) return LWComponent.Alignment.LEFT; else if (mCenterAlignButton.isSelected()) return LWComponent.Alignment.CENTER; else if (mRightAlignButton.isSelected()) return LWComponent.Alignment.RIGHT; else return LWComponent.Alignment.LEFT; } public void displayValue(LWComponent.Alignment align) { //clearAlignmentSelection(); //mLeftAlignButton.setSelected(align.ordinal() == LWComponent.Alignment.LEFT.ordinal() ? true : false); //mCenterAlignButton.setSelected(align.ordinal() == LWComponent.Alignment.CENTER.ordinal() ? true : false); //mRightAlignButton.setSelected(align.ordinal() == LWComponent.Alignment.RIGHT.ordinal() ? true : false); } public void setEnabled(boolean enabled) { //clearAlignmentSelection(); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); } }; mLeftAlignButton.addActionListener(alignmentHandler); mCenterAlignButton.addActionListener(alignmentHandler); mRightAlignButton.addActionListener(alignmentHandler); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); Color[] textColors = VueResources.getColorArray("textColorValues"); //String[] textColorNames = VueResources.getStringArray("textColorNames"); mTextColorButton = new ColorMenuButton(textColors, true); mTextColorButton.setColor(Color.black); mTextColorButton.setPropertyKey(LWKey.TextColor); mTextColorButton.setToolTipText(VueResources.getString("fonteditorpanel.textcolor")); mTextColorButton.addPropertyChangeListener(RichTextColorChangeListener); //Set up Labels... JLabel styleLabel = new JLabel(VueResources.getString("fonteditorpanel.style")); styleLabel.setForeground(new Color(51,51,51)); styleLabel.setFont(tufts.vue.VueConstants.SmallFont); JLabel textLabel = new JLabel(VueResources.getString("fonteditorpanel.text")); textLabel.setLabelFor(mFontCombo); textLabel.setForeground(new Color(51,51,51)); textLabel.setFont(tufts.vue.VueConstants.SmallFont); textLabel.addMouseListener(new MouseAdapter() { // double-click on text color label swaps in with fill color public void mouseClicked(java.awt.event.MouseEvent e) { if (e.getClickCount() > 1 && e.getClickCount() % 2 == 0) { final Color fill = FillToolPanel.mFillColorButton.getColor(); final Color text = mTextColorButton.getColor(); FillToolPanel.mFillColorButton.selectValue(text); mTextColorButton.selectValue(fill); } } }); //Done With Labels.. GridBagConstraints gbc = new GridBagConstraints(); //Layout Panel gbc.gridx=0; gbc.gridy=0; gbc.gridwidth=1; gbc.insets = new Insets(1,3,1,1); gbc.anchor=GridBagConstraints.EAST; gbc.fill=GridBagConstraints.BOTH; add(textLabel,gbc); gbc.gridy=0; gbc.gridx=1; gbc.gridwidth=5; gbc.insets = new Insets(1,3,1,1); gbc.anchor=GridBagConstraints.EAST; gbc.fill=GridBagConstraints.BOTH; add(mFontCombo,gbc); gbc.gridy=0; gbc.gridx=6; gbc.fill=GridBagConstraints.HORIZONTAL; gbc.anchor=GridBagConstraints.CENTER; gbc.gridwidth=3; gbc.weightx=0.5; // gbc.gridheight=1; gbc.ipady=5; //gbc.ipadx=5; gbc.insets=new Insets(1,5,1,1); add(mSizeField,gbc); gbc.anchor=GridBagConstraints.WEST; gbc.gridy=0; gbc.gridx=9; gbc.fill=GridBagConstraints.REMAINDER; gbc.anchor=GridBagConstraints.WEST; gbc.gridheight=1; gbc.gridwidth=1; gbc.ipadx=0; gbc.ipady=0; gbc.insets=new Insets(0,1,1,1); //add(mTextColorButton,gbc); gbc.fill=GridBagConstraints.NONE; gbc.anchor=GridBagConstraints.WEST; gbc.gridwidth=1; gbc.gridheight=0; gbc.gridy=1; gbc.gridx=0; add(styleLabel,gbc); gbc.gridy=1; gbc.gridx=1; mTextColorButton.setPreferredSize(new Dimension(20,20)); boolean isWindows = VueUtil.isWindowsPlatform(); if(!isWindows){ gbc.insets=new Insets(0,5,0,0); } add(mTextColorButton,gbc); gbc.gridy=1; gbc.gridx=2; add(mBoldButton,gbc); gbc.gridy=1; gbc.gridx=3; add(mItalicButton,gbc); gbc.gridy=1; gbc.gridx=4; gbc.fill=GridBagConstraints.NONE; mUnderlineButton.setEnabled(false); add(mUnderlineButton,gbc); gbc.gridy=1; gbc.gridx=5; gbc.fill=GridBagConstraints.NONE; orderedListButton.setEnabled(false); add(orderedListButton,gbc); gbc.gridy=1; gbc.gridx=6; gbc.fill=GridBagConstraints.NONE; unorderedListButton.setEnabled(false); add(unorderedListButton,gbc); gbc.gridy=1; gbc.gridx=7; gbc.insets=new Insets(1,5,1,1); gbc.anchor=GridBagConstraints.EAST; gbc.fill=GridBagConstraints.NONE; add(mLeftAlignButton,gbc); gbc.gridy=1; gbc.gridx=8; gbc.insets=new Insets(1,1,1,1); gbc.anchor=GridBagConstraints.EAST; gbc.fill=GridBagConstraints.NONE; add(mCenterAlignButton,gbc); gbc.gridy=1; gbc.gridx=9; gbc.anchor=GridBagConstraints.WEST; gbc.fill=GridBagConstraints.NONE; add(mRightAlignButton,gbc); //displayValue(VueConstants.FONT_DEFAULT); //initColors(VueTheme.getToolbarColor()); VUE.getFormatDock().setFocusable(true); VUE.getFormatDock().setFocusableWindowState(true); } static int countf = 0; public static ColorMenuButton getTextColorButton() { return mTextColorButton; } private class FontPropertyHandler extends LWPropertyHandler<String> { //new LWPropertyHandler<String>(LWKey.FontName, mFontCombo) { public FontPropertyHandler(JComboBox combo) { super(LWKey.FontName,combo); } public String produceValue() { return (String) mFontCombo.getSelectedItem(); } public void displayValue(String value) { mFontCombo.setSelectedItem(value); } } private class CustomComboBoxRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Color bg = GUI.getTextHighlightColor(); if (isSelected) { setBackground(bg); setForeground(Color.black); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } setText((value == null) ? "" : ((String) value).toString()); return this; } } // public void XpropertyChange(PropertyChangeEvent e) // { // System.out.println("FONTEDITORPANEL: " + e); // /* // if (e instanceof LWPropertyChangeEvent) { // final String propertyName = e.getPropertyName(); // if (mIgnoreEvents) { // if (DEBUG.TOOL) out("propertyChange: skipping " + e + " name=" + propertyName); // return; // } // if (DEBUG.TOOL) out("propertyChange: [" + propertyName + "] " + e); // mIgnoreLWCEvents = true; // VueBeans.applyPropertyValueToSelection(VUE.getSelection(), propertyName, e.getNewValue()); // mIgnoreLWCEvents = false; // if (VUE.getUndoManager() != null) // VUE.getUndoManager().markChangesAsUndo(propertyName); // if (mState != null) // mState.setPropertyValue(propertyName, e.getNewValue()); // else // out("mState is null"); // if (mDefaultState != null) // mDefaultState.setPropertyValue(propertyName, e.getNewValue()); // else // out("mDefaultState is null"); // if (DEBUG.TOOL && DEBUG.META) out("new state " + mState); // } else { // // We're not interested in "ancestor" events, icon change events, etc. // if (DEBUG.TOOL && DEBUG.META) out("ignored AWT/Swing: [" + e.getPropertyName() + "] from " + e.getSource().getClass()); // } // */ // } private void initColors( Color pColor) { mBoldButton.setBackground( pColor); mItalicButton.setBackground( pColor); } public void addNotify() { // if (GUI.isMacAqua()) { // font size edit box asymmetrically tall if left to default // Dimension d = mSizeField.getPreferredSize(); // d.height += 1; // mSizeField.setMaximumSize(d); // } /* still to risky Dimension comboSize = mFontCombo.getPreferredSize(); comboSize.height -= 2; // if too small (eg, -3), will trigger major swing layout bug mFontCombo.setMaximumSize(comboSize); */ /* if (mSizeField.getEditor().getEditorComponent() instanceof JTextField) { JTextField sizeEditor = (JTextField) mSizeField.getEditor().getEditorComponent(); //sizeEditor.setColumns(2); // not exactly character columns sizeEditor.setBackground(VueTheme.getTheme().getMenuBackground()); } */ /* too risky: still can trigger massive swing layout bug Dimension d = mSizeField.getPreferredSize(); // Swing layout is royally buggy: if we add the horizontal strut above, // we need height-2, if we take it out, height-1 -- ! d.height -= 2; mSizeField.setMaximumSize(d); */ mSizeField.setEditable(true); //System.out.println(this + " adding as parent of " + getParent()); super.addNotify(); } /* private boolean mIgnoreActionEvents = false; public void setFontValue(Font font) { if (DEBUG.TOOL) System.out.println(this + " setFontValue " + font); String familyName = font.getFamily(); mIgnoreActionEvents = true; mFontCombo.setSelectedItem(familyName); mItalicButton.setSelected(font.isItalic()); mBoldButton.setSelected(font.isBold()); mSizeField.setSelectedItem(""+font.getSize()); mIgnoreActionEvents = false; } */ /* * @return the current Font represented by the state of the FontEditorPanel public Font getFontValue() { return makeFont(); } */ /* * setValue * Generic property editor access // get rid of this: should be handled in LWPropertyHandler public void setValue( Object pValue) { if( pValue instanceof Font) setFontValue((Font) pValue); } **/ /* private void fireFontChanged( Font pOld, Font pNew) { PropertyChangeListener [] listeners = getPropertyChangeListeners() ; PropertyChangeEvent event = new LWPropertyChangeEvent(this, getPropertyKey(), pOld, pNew); if (listeners != null) { for( int i=0; i<listeners.length; i++) { if (DEBUG.TOOL) System.out.println(this + " fireFontChanged to " + listeners[i]); listeners[i].propertyChange( event); } } } public void actionPerformed(ActionEvent pEvent) { // we've never track the old font value here -- S.B. never finished this code // todo: so this whole thing could probably use a freakin re-write //new Throwable().printStackTrace(); if (mIgnoreActionEvents) { if (DEBUG.TOOL) System.out.println(this + " ActionEvent ignored: " + pEvent.getActionCommand()); } else { if (DEBUG.TOOL) System.out.println(this + " actionPerformed " + pEvent); fireFontChanged(null, makeFont()); } } /** * @return a Font constructed from the current state of the gui elements private Font makeFont() { String name = (String) mFontCombo.getSelectedItem(); int style = Font.PLAIN; if (mItalicButton.isSelected()) style |= Font.ITALIC; if (mBoldButton.isSelected()) style |= Font.BOLD; //int size = (int) mSizeField.getValue(); int size = 12; try { size = Integer.parseInt((String) mSizeField.getSelectedItem()); } catch (Exception e) { System.err.println(e); } return new Font(name, style, size); } */ private int findFontName( String name) { //System.out.println("!!! Searching for font: "+name); for( int i=0; i< sFontNames.length; i++) { if( name.equals( sFontNames[i]) ) { //System.out.println(" FOUND: "+name+" at "+i); return i; } } return -1; } // public Object getPropertyKey() { // return mPropertyKey; // } // public Object produceValue() { // tufts.Util.printStackTrace(this + " asked to produce aggregate value"); // return null; // } // public void displayValue(Object value) { // tufts.Util.printStackTrace(this + " asked to display aggregate value"); // /* // final Font font = (Font) value; // mFontCombo.setSelectedItem(font.getFamily()); // mItalicButton.setSelected(font.isItalic()); // mBoldButton.setSelected(font.isBold()); // mSizeField.setSelectedItem(""+font.getSize()); // */ // } public String toString() { return "FontEditorPanel[" + mPropertyKey + "]"; //return "FontEditorPanel[" + getPropertyKey() + "]"; //return "FontEditorPanel[" + getKey() + " " + makeFont() + "]"; } protected void out(Object o) { System.out.println(this + ": " + (o==null?"null":o.toString())); } // as this can sometimes take a while, we can call this manually // during startup to control when we take the delay. private static Object sFontNamesLock = new Object(); static String[] getFontNames() { synchronized (sFontNamesLock) { if (sFontNames == null){ if (DEBUG.INIT) new Throwable("FYI: loading system fonts...").printStackTrace(); sFontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); } } return sFontNames; } public static void main(String[] args) { System.out.println("FontEditorPanel:main"); DEBUG.Enabled = DEBUG.INIT = true; VUE.init(args); //sFontNames = new String[] { "Lucida Sans Typewriter", "Courier", "Arial" }; // so doesn't bother to load system fonts VueUtil.displayComponent(new FontEditorPanel(LWKey.Font)); } private void enableSupportedEditors() { setSpecialEditorsEnabled(true); mBoldButton.setEnabled(true); mItalicButton.setEnabled(true); mFontCombo.setEnabled(true); mSizeField.setEnabled(true); mTextColorButton.setEnabled(true); mLeftAlignButton.setEnabled(true); mCenterAlignButton.setEnabled(true); mRightAlignButton.setEnabled(true); } private void disableSpecialEditors() { // we only need to disable the editors not associated with // a property (those special to LWText) -- the rest of // the editors will set their enabled state based on what's // next selected. setSpecialEditorsEnabled(false); } public String colorToString(Color c) { char[] buf = new char[7]; buf[0] = '#'; String s = Integer.toHexString(c.getRed()); if (s.length() == 1) { buf[1] = '0'; buf[2] = s.charAt(0); } else { buf[1] = s.charAt(0); buf[2] = s.charAt(1); } s = Integer.toHexString(c.getGreen()); if (s.length() == 1) { buf[3] = '0'; buf[4] = s.charAt(0); } else { buf[3] = s.charAt(0); buf[4] = s.charAt(1); } s = Integer.toHexString(c.getBlue()); if (s.length() == 1) { buf[5] = '0'; buf[6] = s.charAt(0); } else { buf[5] = s.charAt(0); buf[6] = s.charAt(1); } return String.valueOf(buf); } private void setSpecialEditorsEnabled(boolean enabled) { mUnderlineButton.setEnabled(enabled); orderedListButton.setEnabled(enabled); unorderedListButton.setEnabled(enabled); Color c = null; if (VUE.getActiveViewer().getFocal() instanceof LWSlide) c = ((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getTextColor(); else c = mTextColorButton.getColor(); toggleBulletsAction.setColor(colorToString(c)); toggleNumbersAction.setColor(colorToString(c)); } // private final ActionListener TextColorListener = // new ActionListener() { // public void actionPerformed(ActionEvent e) // { // Color color =FontEditorPanel.getTextColorButton().getColor(); // SimpleAttributeSet set = new SimpleAttributeSet(); // String colorString = "#" + Integer.toHexString(color.getRGB()).substring(2); // Util.styleSheet().addCSSAttribute(set, // CSS.Attribute.COLOR, colorString); // set.addAttribute(HTML.Attribute.COLOR, colorString); // //text.getRichLabelBox().applyAttributes(set, false); // ((RichTextBox)VUE.getActive(RichTextBox.class)).applyAttributes(set, false); // } // }; /** * We need to use a property change listener instead of an action listener for the * ColorMenuButton, as the action fires there to detect popping the menu, not * a color set. When a color is picked, it will fire off property change events * to any listeners. We set ourselves up to listen constantly here, and * if there is an active RichTextBox editing, then we apply it, otherwise we * just ignore it. */ private final PropertyChangeListener RichTextColorChangeListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e instanceof LWPropertyChangeEvent == false) return; final RichTextBox activeRTB = (RichTextBox) VUE.getActive(RichTextBox.class); if (activeRTB == null && lwtext == null) { // no problem: just ignore if there's no active edit //tufts.Util.printStackTrace("FEP propertyChange: no active RichTextBox: " + e); return; } if (lwtext !=null) lwtext.richLabelBox.selectAll(); final Color color = (Color) e.getNewValue(); final SimpleAttributeSet set = new SimpleAttributeSet(); final String colorString = "#" + Integer.toHexString(color.getRGB()).substring(2); toggleBulletsAction.setColor(colorString); toggleNumbersAction.setColor(colorString); Util.styleSheet().addCSSAttribute(set, CSS.Attribute.COLOR, colorString); set.addAttribute(HTML.Attribute.COLOR, colorString); if (activeRTB != null) activeRTB.applyAttributes(set, false); else lwtext.richLabelBox.applyAttributes(set, false); if (lwtext !=null) { lwtext.richLabelBox.select(0,0); lwtext.richLabelBox.select(0,0); //lwtext.setLabel0(lwtext.richLabelBox.getRichText(), false); lwtext.richLabelBox.setSize(lwtext.richLabelBox.getPreferredSize()); if (lwtext.getParent() !=null) lwtext.getParent().layout(); lwtext.notify(lwtext.richLabelBox, LWKey.Repaint); } } }; private void setEditorPanes(RichTextBox activeText) { richBoldAction.setEditorPane(activeText); richItalicAction.setEditorPane(activeText); richUnderlineAction.setEditorPane(activeText); toggleBulletsAction.setEditorPane(activeText); toggleNumbersAction.setEditorPane(activeText); paraAlignLeftAction.setEditorPane(activeText); paraAlignCenterAction.setEditorPane(activeText); paraAlignRightAction.setEditorPane(activeText); fontFamilyAction.setEditorPane(activeText); fontSizeAction.setEditorPane(activeText); fontColorAction.setEditorPane(activeText); } private boolean LWTextListenersAdded = false; private boolean RTBListenersAdded =false; private boolean defaultListenersAdded=false; private void establishLWTextListeners(LWComponent activeText) { if (DEBUG_FONTPANEL) System.out.println("ESTABLISH LWT Listeners"); breakdownDefaultListeners(); //clearAlignmentSelection(); VUE.getFormatDock().setFocusable(false); VUE.getFormatDock().setFocusableWindowState(false); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); //System.out.println("lw text"); mFontCombo.setEnabled(true); mSizeField.setEnabled(true); mTextColorButton.setEnabled(true); lwtext = (LWText)activeText; //MK lwtext.richLabelBox.removeCaretListener(this); updateFormatControlsTB(lwtext.richLabelBox); //mFontCombo.removeActionListener(fontPropertyHandler); //mSizeField.removeActionListener(sizeHandler); //EditorManager.unregisterEditor(sizeHandler); //EditorManager.unregisterEditor(fontPropertyHandler); mBoldButton.addActionListener(globalBoldListener); mUnderlineButton.addActionListener(globalUnderlineListener); mItalicButton.addActionListener(globalItalicListener); mSizeField.addActionListener(globalSizeListener); mFontCombo.addActionListener(globalFaceListener); LWTextListenersAdded = true; } private void breakdownRichTextListeners(RichTextBox activeText) { //MK activeText.removeCaretListener(this); breakdownRichTextListeners(); } private void breakdownLWTextListeners() { if (DEBUG_FONTPANEL) System.out.println("BREAKDOWN LWT Listeners"); lwtext=null; //System.out.println("lost lw text"); // clearAlignmentSelection(); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); mSizeField.removeActionListener(globalSizeListener); mFontCombo.removeActionListener(globalFaceListener); stripAllListeners(mBoldButton); stripAllListeners(mItalicButton); stripAllListeners(mUnderlineButton); LWTextListenersAdded = false; establishDefaultListeners(); } private void breakdownRichTextListeners() { if (DEBUG_FONTPANEL) System.out.println("BREAKDOWN RTB Listeners"); //System.out.println("lost rtb rich text box"); disableSpecialEditors(); clearAlignmentSelection(); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); VUE.getFormatDock().setFocusable(true); VUE.getFormatDock().setFocusableWindowState(true); stripAllListeners(mBoldButton); stripAllListeners(mItalicButton); stripAllListeners(mUnderlineButton); mFontCombo.removeActionListener(fontFamilyActionWrapper); // mFontCombo.addActionListener(fontPropertyHandler); mSizeField.removeActionListener(fontSizeActionWrapper); // mSizeField.addActionListener(fontPropertyHandler); mLeftAlignButton.removeActionListener(paraAlignLeftActionWrapper); mCenterAlignButton.removeActionListener(paraAlignCenterActionWrapper); mRightAlignButton.removeActionListener(paraAlignRightActionWrapper); RTBListenersAdded = false; //establishDefaultListeners(); } private void stripAllListeners(AbstractButton b) { ActionListener[] l = b.getListeners(ActionListener.class); for (int i=0;i<l.length;i++) b.removeActionListener(l[i]); return; } private void establishRichTextListeners(RichTextBox activeText) { if (DEBUG_FONTPANEL) System.out.println("ESTABLISH RTB Listeners"); breakdownDefaultListeners(); //System.out.println("rtb rich text box"); activeText.addCaretListener(this); setEditorPanes(activeText); // clearAlignmentSelection(); mLeftAlignButton.setEnabled(true); mCenterAlignButton.setEnabled(true); mRightAlignButton.setEnabled(true); activeText.setToggleBulletList(toggleBulletsAction); activeText.setNumberList(toggleNumbersAction); mBoldButton.addActionListener(richBoldActionWrapper); mItalicButton.addActionListener(richItalicActionWrapper); mUnderlineButton.addActionListener(richUnderlineActionWrapper); mFontCombo.addActionListener(fontFamilyActionWrapper); mSizeField.addActionListener(fontSizeActionWrapper); mLeftAlignButton.addActionListener(paraAlignLeftActionWrapper); mCenterAlignButton.addActionListener(paraAlignCenterActionWrapper); mRightAlignButton.addActionListener(paraAlignRightActionWrapper); enableSupportedEditors(); RTBListenersAdded = true; } public void establishDefaultListeners() { if (DEBUG_FONTPANEL) System.out.println("ESTABLISH Default Listeners"); VUE.getFormatDock().setFocusable(true); VUE.getFormatDock().setFocusableWindowState(true); clearAlignmentSelection(); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); // if (!EditorManager.isRegistered(sizeHandler)) // EditorManager.registerEditor(sizeHandler); // if (!EditorManager.isRegistered(fontPropertyHandler)) // EditorManager.registerEditor(fontPropertyHandler); mBoldButton.addActionListener(styleChangeHandler); mItalicButton.addActionListener(styleChangeHandler); mUnderlineButton.addActionListener(underlineChangeHandler); mFontCombo.addActionListener(fontPropertyHandler); mSizeField.addActionListener(fontPropertyHandler); mLeftAlignButton.addActionListener(alignmentHandler); mCenterAlignButton.addActionListener(alignmentHandler); mRightAlignButton.addActionListener(alignmentHandler); defaultListenersAdded=true; } public void breakdownDefaultListeners() { if (DEBUG_FONTPANEL) System.out.println("BREAKDOWN Default Listeners"); // EditorManager.unregisterEditor(sizeHandler); // EditorManager.unregisterEditor(fontPropertyHandler); //clearAlignmentSelection(); mLeftAlignButton.setEnabled(false); mCenterAlignButton.setEnabled(false); mRightAlignButton.setEnabled(false); mLeftAlignButton.removeActionListener(alignmentHandler); mCenterAlignButton.removeActionListener(alignmentHandler); mRightAlignButton.removeActionListener(alignmentHandler); stripAllListeners(mBoldButton); stripAllListeners(mItalicButton); stripAllListeners(mUnderlineButton); mFontCombo.removeActionListener(fontPropertyHandler); mSizeField.removeActionListener(fontPropertyHandler); defaultListenersAdded=false; } public void clearAlignmentSelection() { SwingUtilities.invokeLater(new Runnable() { public void run() { buttonGroup.remove(mLeftAlignButton); buttonGroup.remove(mCenterAlignButton); buttonGroup.remove(mRightAlignButton); mLeftAlignButton.setSelected(false); mCenterAlignButton.setSelected(false); mRightAlignButton.setSelected(false); buttonGroup.add(mLeftAlignButton); buttonGroup.add(mCenterAlignButton); buttonGroup.add(mRightAlignButton); } }); } private static boolean isRichTextActive = false; public void activeChanged(final ActiveEvent e, LWComponent activeText) { //System.out.println("lwtext new active : " + e.active + " Old active : " + e.oldActive); suspendItemListeners=true; if (RTBListenersAdded) breakdownRichTextListeners(); if (e.oldActive instanceof LWText) { if (LWTextListenersAdded) breakdownLWTextListeners(); } if (e.active != null && e.oldActive != null && e.active instanceof LWText && e.oldActive instanceof LWText) { breakdownLWTextListeners(); establishLWTextListeners(activeText); ((LWText)e.active).richLabelBox.setCaretPosition(2); updateFormatControlsTB(((LWText)e.active).richLabelBox); // System.out.println("OUT"); suspendItemListeners=false; return; } if (e.active instanceof LWText) { if (RTBListenersAdded) breakdownRichTextListeners(); if (!LWTextListenersAdded) { establishLWTextListeners(activeText); } ((LWText)e.active).richLabelBox.setCaretPosition(2); updateFormatControlsTB(((LWText)e.active).richLabelBox); } else { if (!defaultListenersAdded) establishDefaultListeners(); } suspendItemListeners=false; } public void activeChanged(ActiveEvent e, RichTextBox activeText) { if (e.active == e.oldActive) return; if (e.active == null) return; suspendItemListeners=true; // System.out.println("new active : " + e.active + " Old active : " + e.oldActive); if (e.active != null) { if (LWTextListenersAdded) breakdownLWTextListeners(); if (!RTBListenersAdded) establishRichTextListeners(activeText); } else if (e.oldActive instanceof RichTextBox) { if (RTBListenersAdded) breakdownRichTextListeners(); } suspendItemListeners=false; } public AttributeSet getMaxAttributes(RichTextBox text,final int caretPosition) { final Element paragraphElement = ((SHTMLDocument)text.getDocument()).getParagraphElement(caretPosition); final StyleSheet styleSheet = ((SHTMLDocument)text.getDocument()).getStyleSheet(); return SHTMLPanelImpl.getMaxAttributes(paragraphElement, styleSheet); } AttributeSet getMaxAttributes(RichTextBox editorPane, String elemName) { SHTMLDocument doc = (SHTMLDocument)editorPane.getDocument(); Element e = doc.getCharacterElement(editorPane.getSelectionStart()); StyleSheet s = doc.getStyleSheet(); if(elemName != null && elemName.length() > 0) { e = Util.findElementUp(elemName, e); return SHTMLPanelImpl.getMaxAttributes(e, s); } final MutableAttributeSet maxAttributes = (MutableAttributeSet)SHTMLPanelImpl.getMaxAttributes(e, s); final StyledEditorKit editorKit = (StyledEditorKit)editorPane.getEditorKit(); final MutableAttributeSet inputAttributes = editorKit.getInputAttributes(); maxAttributes.addAttributes(inputAttributes); return maxAttributes; } private final void updateFormatControls(CaretEvent e) { if (suspendItemListeners) return; if (e != null) updateFormatControlsTB((RichTextBox)e.getSource()); else updateFormatControlsTB(null); } public final void updateFormatControlsTB(RichTextBox text) { SHTMLDocument doc = (SHTMLDocument)text.getDocument(); int so = text.getSelectionStart(); int eo = text.getSelectionEnd(); int caretPosition = 0; if (so != eo && Math.abs(eo-so) > 1) { caretPosition=so; } else { caretPosition = text.getCaretPosition(); } //Assembling appropriate attribute sets //System.out.println("Caret position : " + text.getCaretPosition()); Element paragraphElement = doc.getParagraphElement(caretPosition); if (paragraphElement.getName().equals("p-implied")) //we're in a list item paragraphElement = paragraphElement.getParentElement(); AttributeSet paragraphAttributeSet = paragraphElement.getAttributes(); Element charElem = null; if (so != eo && Math.abs(eo-so) > 1) charElem = doc.getCharacterElement(caretPosition); else charElem = doc.getCharacterElement(caretPosition > 0 ? caretPosition-1 : 1); AttributeSet charSet = charElem.getAttributes(); Enumeration characterAttributeEnum = charSet.getAttributeNames(); Enumeration elementEnum = paragraphAttributeSet.getAttributeNames(); // Done Assembling appropriate attribute sets //************************************ SET DEFAULTS //Start with all these turned off. mBoldButton.setSelected(false); mItalicButton.setSelected(false); mUnderlineButton.setSelected(false); //Set Font size / face defaults. if (VUE.getActiveViewer().getFocal() instanceof LWSlide) { Font f = ((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getFont(); mSizeField.getEditor().setItem(Integer.toString(f.getSize())); mFontCombo.getEditor().setItem(f.getFontName()); } else { Style r = doc.getStyleSheet().getRule("ul"); mSizeField.getEditor().setItem(r.getAttribute(CSS.Attribute.FONT_SIZE)); String s = r.getAttribute(CSS.Attribute.FONT_FAMILY).toString(); int p = s.indexOf(","); s = s.substring(0,p > 0 ? p : s.length()); if (s.length() > 1) mFontCombo.getEditor().setItem(s); } //end font size /face defaults. //set the default color if (VUE.getActiveViewer().getFocal() instanceof LWSlide) { Color c = ((LWSlide)VUE.getActivePathway().getMasterSlide()).getMasterSlide().getTextStyle().getTextColor(); //System.out.println("LW SLIDE : " + c.toString()); mTextColorButton.setColor(c); } else mTextColorButton.setColor(Color.black); //done setting the default color. //**********************************************DONE SETTING DEFAULTS //If you're looking at a selection blank out the size and face combos unselect //every other relevant field and return there's not much we can do here. //if (so != eo && Math.abs(eo-so) > 1) // { // System.out.println("so : " + so + " eo : " + eo); //blank out the appropriate fields, set stuff unselected and return //mSizeField.getEditor().setItem(""); //mFontCombo.getEditor().setItem(""); // while (elementEnum.hasMoreElements()) // { // Object o = elementEnum.nextElement(); // if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("left")) // mLeftAlignButton.setSelected(true); // else if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("center")) // mCenterAlignButton.setSelected(true); // else if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("right")) // mRightAlignButton.setSelected(true); // } // } while (elementEnum.hasMoreElements()) { Object o = elementEnum.nextElement(); //System.out.println("pargraph element : " + o.toString() + " , " + paragraphAttributeSet.getAttribute(o)); //if (o.toString().equals("text-align")) //System.out.println(" P: " + o.toString() + " *** " + .getAttribute(o).toString()); boolean isAlignSet = false; if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("left") && !isAlignSet) {// System.out.println("SET LEFT"); //isAlignSet = true; mLeftAlignButton.setSelected(true); } else if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("center")&& !isAlignSet) { //System.out.println("SET CENTER"); //isAlignSet = true; mCenterAlignButton.setSelected(true); } else if (o.toString().equals("text-align") && paragraphAttributeSet.getAttribute(o).toString().equals("right")&& !isAlignSet) { // isAlignSet = true; mRightAlignButton.setSelected(true); } if ((o.toString().equals("font-size")) ||(o.toString().equals("size"))) { mSizeField.getEditor().setItem(paragraphAttributeSet.getAttribute(o).toString()); EditorManager.setEditorLoading(true); mSizeField.getModel().setSelectedItem(paragraphAttributeSet.getAttribute(o).toString()); EditorManager.setEditorLoading(false); } else if ((o.toString().equals("font-family")) || (o.toString().equals("font-face")) || (o.toString().equals("face"))) { mFontCombo.getEditor().setItem(paragraphAttributeSet.getAttribute(o).toString()); suspendItemListeners = true; EditorManager.setEditorLoading(true); mFontCombo.getModel().setSelectedItem(paragraphAttributeSet.getAttribute(o).toString()); EditorManager.setEditorLoading(false); suspendItemListeners = false; } } while (characterAttributeEnum.hasMoreElements()) { Object o = characterAttributeEnum.nextElement(); //System.out.println("Character element : " + o.toString() + " , " + charSet.getAttribute(o)); if ((o.toString().equals("color"))) mTextColorButton.setColor(edu.tufts.vue.style.Style.hexToColor(charSet.getAttribute(o).toString())); if ((o.toString().equals("font-size")) ||(o.toString().equals("size"))) { mSizeField.getEditor().setItem(charSet.getAttribute(o).toString()); suspendItemListeners = true; EditorManager.setEditorLoading(true); mSizeField.getModel().setSelectedItem(charSet.getAttribute(o).toString()); EditorManager.setEditorLoading(false); suspendItemListeners = false; } if ((o.toString().equals("font-family")) || (o.toString().equals("font-face")) || (o.toString().equals("face"))) { mFontCombo.getEditor().setItem(charSet.getAttribute(o).toString()); suspendItemListeners = true; EditorManager.setEditorLoading(true); mFontCombo.getModel().setSelectedItem(charSet.getAttribute(o).toString()); EditorManager.setEditorLoading(false); suspendItemListeners = false; } if ((o.toString().equals("font-weight") && charSet.getAttribute(o).toString().equals("bold")) || o.toString().equals("b")) { EditorManager.setEditorLoading(true); mBoldButton.setSelected(true); EditorManager.setEditorLoading(false); } if ((o.toString().equals("font-style") && charSet.getAttribute(o).toString().equals("italic")) || o.toString().equals("i")) { EditorManager.setEditorLoading(true); mItalicButton.setSelected(true); EditorManager.setEditorLoading(false); } if ((o.toString().equals("text-decoration") && charSet.getAttribute(o).toString().equals("underline")) || o.toString().equals("u")) { EditorManager.setEditorLoading(true); mUnderlineButton.setSelected(true); EditorManager.setEditorLoading(false); } }//done looking at character attributes } public void caretUpdate(final CaretEvent e) { EventQueue.invokeLater(new Runnable(){ public void run() { updateFormatControls(e); } }); } public void componentHidden(ComponentEvent arg0) { // TODO Auto-generated method stub } public void componentMoved(ComponentEvent arg0) { if (mTextColorButton.getPopupWindow().isVisible()) mTextColorButton.getPopupWindow().setVisible(false); } public void componentResized(ComponentEvent arg0) { // TODO Auto-generated method stub } public void componentShown(ComponentEvent arg0) { // TODO Auto-generated method stub } }