/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.properties;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ToolBar;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.IViewer;
import org.xmind.gef.Request;
import org.xmind.gef.graphicalpolicy.IStyleSelector;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.ui.color.ColorPicker;
import org.xmind.ui.color.ColorSelection;
import org.xmind.ui.color.IColorSelection;
import org.xmind.ui.color.PaletteContents;
import org.xmind.ui.commands.CommandMessages;
import org.xmind.ui.font.FontDialog;
import org.xmind.ui.font.IFontChooser;
import org.xmind.ui.font.IFontChooserListener;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.properties.StyledPropertySectionPart;
import org.xmind.ui.resources.ColorUtils;
import org.xmind.ui.resources.FontUtils;
import org.xmind.ui.resources.FontUtils.IFontNameListCallback;
import org.xmind.ui.richtext.AlignmentGroup;
import org.xmind.ui.style.StyleUtils;
import org.xmind.ui.style.Styles;
import org.xmind.ui.style.TextStyleData;
import org.xmind.ui.util.MindMapUtils;
import org.xmind.ui.viewers.MComboViewer;
public class FontPropertySectionPart extends StyledPropertySectionPart {
private class FontLabelProvider extends LabelProvider {
}
private class FontSelectionChangedListener implements
ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
if (isRefreshing())
return;
Object o = ((IStructuredSelection) event.getSelection())
.getFirstElement();
if (o instanceof String) {
changeFontName((String) o);
}
}
}
private class ChooseFontAction extends Action {
public ChooseFontAction() {
super(null, MindMapUI.getImages().get(IMindMapImages.TEXT_FONT,
true));
setToolTipText(PropertyMessages.ChooseFont_toolTip);
}
public void run() {
if (currentTextStyle == null)
return;
FontDialog dialog = new FontDialog(getContainer()
.getContainerSite().getShell());
if (currentTextStyle != null) {
if (currentTextStyle.name != null)
dialog.setFontName(currentTextStyle.name);
if (currentTextStyle.height > 0)
dialog.setFontHeight(currentTextStyle.height);
dialog.setBold(currentTextStyle.bold);
dialog.setItalic(currentTextStyle.italic);
if (currentTextStyle.color != null)
dialog.setColor(currentTextStyle.color);
dialog.setUnderline(currentTextStyle.underline);
dialog.setStrikeout(currentTextStyle.strikeout);
}
dialog.addFontChooserListener(new IFontChooserListener() {
public void fontChanged(IFontChooser source) {
showTempFont(source);
}
});
int ret = dialog.open();
showTempFont(null);
if (ret == FontDialog.OK) {
changeFont(dialog.getFontName(), dialog.getFontHeight(), dialog
.getBold(), dialog.getItalic(), dialog.getUnderline(),
dialog.getStrikeout(), dialog.getColor());
}
}
}
private class SizeLabelProvider extends LabelProvider {
}
private class SizeSelectionChangedListener implements
ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
if (isRefreshing())
return;
Object o = ((IStructuredSelection) event.getSelection())
.getFirstElement();
if (o instanceof String) {
try {
int i = Integer.parseInt((String) o);
FONT_SIZE_LIST.add(i);
changeFontSize(i);
} catch (NumberFormatException e) {
}
} else if (o instanceof Integer) {
changeFontSize(((Integer) o).intValue());
}
}
}
private class BoldAction extends Action {
public BoldAction() {
super(null, MindMapUI.getImages().get(IMindMapImages.TEXT_BOLD,
true));
setToolTipText(PropertyMessages.Bold_toolTip);
setChecked(false);
}
public void run() {
super.run();
changeBold(isChecked());
}
}
private class ItalicAction extends Action {
public ItalicAction() {
super(null, MindMapUI.getImages().get(IMindMapImages.TEXT_ITALIC,
true));
setToolTipText(PropertyMessages.Italic_toolTip);
setChecked(false);
}
public void run() {
super.run();
changeItalic(isChecked());
}
}
private class StrikeoutAction extends Action {
public StrikeoutAction() {
super(null, MindMapUI.getImages().get(
IMindMapImages.TEXT_STRIKEOUT, true));
setToolTipText(PropertyMessages.Strikeout_toolTip);
setChecked(false);
}
public void run() {
super.run();
changeStrikeout(isChecked());
}
}
private class AlignLeftAction extends Action {
public AlignLeftAction() {
super(PropertyMessages.TextAlignLeft_text, MindMapUI.getImages()
.get(IMindMapImages.ALIGN_LEFT, true));
setToolTipText(PropertyMessages.TextAlignLeft_toolTip);
setChecked(false);
}
public void run() {
changeAlignLeft();
}
}
private class AlignCenterAction extends Action {
public AlignCenterAction() {
super(PropertyMessages.TextAlignCenter_text, MindMapUI.getImages()
.get(IMindMapImages.ALIGN_CENTER, true));
setToolTipText(PropertyMessages.TextAlignCenter_toolTip);
setChecked(false);
}
public void run() {
changeAlignCenter();
}
}
private class AlignRightAction extends Action {
public AlignRightAction() {
super(PropertyMessages.TextAlignRight_text, MindMapUI.getImages()
.get(IMindMapImages.ALIGN_RIGHT, true));
setToolTipText(PropertyMessages.TextAlignRight_toolTip);
setChecked(false);
}
public void run() {
changeAlignRight();
}
}
private class ColorOpenListener implements IOpenListener {
public void open(OpenEvent event) {
changeTextColor((IColorSelection) event.getSelection());
}
}
private static Set<Integer> FONT_SIZE_LIST = new TreeSet<Integer>();
private IAction boldAction;
private IAction italicAction;
private IAction strikeoutAction;
private MComboViewer fontViewer;
private MComboViewer sizeViewer;
private TextStyleData currentTextStyle;
private ColorPicker textColorPicker;
private AlignmentGroup alignGroup;
private IAction alignLeftAction;
private IAction alignCenterAction;
private IAction alignRightAction;
protected void createContent(Composite parent) {
Composite line1 = new Composite(parent, SWT.NONE);
line1.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
false));
GridLayout layout1 = new GridLayout(2, false);
layout1.marginWidth = 0;
layout1.marginHeight = 0;
layout1.horizontalSpacing = 3;
layout1.verticalSpacing = 3;
line1.setLayout(layout1);
createLineContent1(line1);
Composite line2 = new Composite(parent, SWT.NONE);
line2.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
false));
GridLayout layout2 = new GridLayout(2, false);
layout2.marginWidth = 0;
layout2.marginHeight = 0;
layout2.horizontalSpacing = 3;
layout2.verticalSpacing = 3;
line2.setLayout(layout2);
createLineContent2(line2);
}
private void createLineContent1(Composite parent) {
fontViewer = new MComboViewer(parent, MComboViewer.FILTERED);
fontViewer.getControl().setLayoutData(
new GridData(GridData.FILL, GridData.FILL, true, false));
fontViewer.getControl().setToolTipText(
PropertyMessages.FontFamily_toolTip);
fontViewer.setContentProvider(new ArrayContentProvider());
fontViewer.setLabelProvider(new FontLabelProvider());
fontViewer.getControl().setEnabled(false);
IFontNameListCallback callback = new IFontNameListCallback() {
public void setAvailableFontNames(List<String> fontNames) {
if (fontViewer == null || fontViewer.getControl().isDisposed())
return;
fontViewer.getControl().setEnabled(true);
fontViewer.setInput(fontNames);
TextStyleData ts = calcCurrentTextStyle();
if (ts != null && ts.name != null) {
fontViewer.setSelection(new StructuredSelection(ts.name));
}
fontViewer
.addSelectionChangedListener(new FontSelectionChangedListener());
}
};
FontUtils.fetchAvailableFontNames(parent.getDisplay(), callback);
ToolBarManager fontBar = new ToolBarManager(SWT.FLAT);
fontBar.add(new ChooseFontAction());
ToolBar barControl = fontBar.createControl(parent);
barControl.setLayoutData(new GridData(GridData.END, GridData.CENTER,
false, false));
}
private void createLineContent2(Composite parent) {
sizeViewer = new MComboViewer(parent, MComboViewer.FILTERED);
sizeViewer.getControl().setLayoutData(
new GridData(GridData.FILL, GridData.FILL, true, false));
sizeViewer.getControl().setToolTipText(
PropertyMessages.FontSize_toolTip);
sizeViewer.setContentProvider(new ArrayContentProvider());
sizeViewer.setLabelProvider(new SizeLabelProvider());
sizeViewer.setPermitsUnprovidedElement(true);
if (FONT_SIZE_LIST.isEmpty()) {
FONT_SIZE_LIST.addAll(Arrays.asList(8, 9, 10, 11, 12, 14, 16, 18,
20, 22, 24, 36, 48, 56));
}
sizeViewer.setInput(FONT_SIZE_LIST);
sizeViewer
.addSelectionChangedListener(new SizeSelectionChangedListener());
ToolBarManager styleBar = new ToolBarManager(SWT.FLAT);
styleBar.add(boldAction = new BoldAction());
styleBar.add(italicAction = new ItalicAction());
styleBar.add(strikeoutAction = new StrikeoutAction());
textColorPicker = new ColorPicker(
ColorPicker.AUTO | ColorPicker.CUSTOM, PaletteContents
.getDefault());
textColorPicker.getAction().setToolTipText(
PropertyMessages.TextColor_toolTip);
textColorPicker.addOpenListener(new ColorOpenListener());
styleBar.add(textColorPicker);
alignGroup = new AlignmentGroup();
alignGroup.add(alignLeftAction = new AlignLeftAction());
alignGroup.add(alignCenterAction = new AlignCenterAction());
alignGroup.add(alignRightAction = new AlignRightAction());
styleBar.add(alignGroup);
ToolBar barControl = styleBar.createControl(parent);
barControl.setLayoutData(new GridData(GridData.END, GridData.CENTER,
false, false));
}
protected void doRefresh() {
TextStyleData ts = calcCurrentTextStyle();
currentTextStyle = ts;
if (fontViewer != null && !fontViewer.getControl().isDisposed()
&& fontViewer.getControl().isEnabled()) {
fontViewer
.setSelection(ts == null || ts.name == null ? StructuredSelection.EMPTY
: new StructuredSelection(ts.name));
}
if (sizeViewer != null && !sizeViewer.getControl().isDisposed()) {
sizeViewer
.setSelection(ts == null || ts.height < 0 ? StructuredSelection.EMPTY
: new StructuredSelection(Integer
.valueOf(ts.height)));
}
if (boldAction != null)
boldAction.setChecked(ts != null && ts.bold);
if (italicAction != null)
italicAction.setChecked(ts != null && ts.italic);
if (strikeoutAction != null)
strikeoutAction.setChecked(ts != null && ts.strikeout);
if (textColorPicker != null)
updateColorPicker(textColorPicker);
switch (ts == null ? PositionConstants.LEFT : ts.align) {
case PositionConstants.LEFT:
if (alignLeftAction != null)
alignLeftAction.setChecked(ts != null);
break;
case PositionConstants.CENTER:
if (alignCenterAction != null)
alignCenterAction.setChecked(ts != null);
break;
case PositionConstants.RIGHT:
if (alignRightAction != null)
alignRightAction.setChecked(ts != null);
break;
}
}
private void updateColorPicker(ColorPicker picker) {
if (currentTextStyle == null || currentTextStyle.color == null) {
picker.setSelection(ColorSelection.EMPTY);
picker.setAutoColor(null);
} else {
IGraphicalPart part = getGraphicalPart(getSelectedElements()[0]);
IStyleSelector ss = getStyleSelector(part);
String autoValue = ss.getAutoValue(part, Styles.TextColor);
RGB autoColor = StyleUtils.convertRGB(Styles.TextColor, autoValue);
picker.setAutoColor(autoColor);
String userValue = ss.getUserValue(part, Styles.TextColor);
int type;
if (userValue == null) {
type = IColorSelection.AUTO;
userValue = autoValue;
} else {
type = IColorSelection.CUSTOM;
}
if (type != IColorSelection.AUTO && Styles.NONE.equals(userValue)) {
type = IColorSelection.NONE;
}
RGB color = StyleUtils.convertRGB(Styles.TextColor, userValue);
picker.setSelection(new ColorSelection(type, color));
}
}
protected TextStyleData calcCurrentTextStyle() {
TextStyleData textStyle = null;
IViewer viewer = getActiveViewer();
if (viewer != null) {
for (Object o : getSelectedElements()) {
IGraphicalPart part = getGraphicalPart(o, viewer);
if (part != null) {
IStyleSelector ss = getStyleSelector(part);
TextStyleData ts = calcTextStyle(part, ss);
if (ts == null)
return null;
textStyle = mergeStyle(textStyle, ts);
if (textStyle.name == null && textStyle.height < 0
&& textStyle.color == null && !textStyle.italic
&& !textStyle.bold && !textStyle.underline
&& !textStyle.strikeout
/* && textStyle.align == 0 */) {
textStyle = null;
break;
}
}
}
}
return textStyle;
}
private TextStyleData mergeStyle(TextStyleData source, TextStyleData target) {
if (source == null)
return new TextStyleData(target);
if (source.name != null && !source.name.equals(target.name))
source.name = null;
if (source.height > 0 && source.height != target.height)
source.height = -1;
if (source.italic && !target.italic)
source.italic = false;
if (source.bold && !target.bold)
source.bold = false;
if (source.color != null && !source.color.equals(target.color))
source.color = null;
if (source.strikeout && !target.strikeout)
source.strikeout = false;
if (source.underline && !target.underline)
source.underline = false;
if (source.align != target.align)
source.align = SWT.LEFT;
return source;
}
private TextStyleData calcTextStyle(IGraphicalPart part, IStyleSelector ss) {
return StyleUtils.getTextStyleData(part, ss, null);
}
public void setFocus() {
if (fontViewer != null && !fontViewer.getControl().isDisposed()) {
fontViewer.getControl().setFocus();
}
}
public void dispose() {
super.dispose();
fontViewer = null;
sizeViewer = null;
currentTextStyle = null;
boldAction = null;
italicAction = null;
strikeoutAction = null;
currentTextStyle = null;
textColorPicker = null;
alignLeftAction = null;
alignCenterAction = null;
alignRightAction = null;
}
private void changeFontName(String name) {
sendRequest(addStyle(
createStyleRequest(CommandMessages.Command_ModifyFont),
Styles.FontFamily, name));
}
private void changeFont(String fontName, int fontHeight, boolean bold,
boolean italic, boolean underline, boolean strikeout, RGB color) {
Request req = createStyleRequest(CommandMessages.Command_ModifyFont);
if (fontName != null)
addStyle(req, Styles.FontFamily, fontName);
if (fontHeight > 0)
addStyle(req, Styles.FontSize, StyleUtils.addUnitPoint(fontHeight));
addStyle(req, Styles.FontWeight, bold ? Styles.FONT_WEIGHT_BOLD
: Styles.NORMAL);
addStyle(req, Styles.FontStyle, italic ? Styles.FONT_STYLE_ITALIC
: Styles.NORMAL);
addStyle(req, Styles.TextDecoration, StyleUtils.toTextDecoration(
underline, strikeout));
addStyle(req, Styles.TextColor, color == null ? null : ColorUtils
.toString(color));
sendRequest(req);
}
private void changeFontSize(int fontHeight) {
sendRequest(addStyle(
createStyleRequest(CommandMessages.Command_ModifyFont),
Styles.FontSize, StyleUtils.addUnitPoint(fontHeight)));
}
private void changeBold(boolean bold) {
sendRequest(addStyle(
createStyleRequest(CommandMessages.Command_ModifyFont),
Styles.FontWeight, bold ? Styles.FONT_WEIGHT_BOLD
: Styles.NORMAL));
}
private void changeItalic(boolean italic) {
sendRequest(addStyle(
createStyleRequest(CommandMessages.Command_ModifyFont),
Styles.FontStyle, italic ? Styles.FONT_STYLE_ITALIC
: Styles.NORMAL));
}
private void changeStrikeout(boolean strikeout) {
String decoration = null;
if (currentTextStyle != null && currentTextStyle.underline) {
decoration = Styles.TEXT_DECORATION_UNDERLINE;
}
if (decoration == null) {
decoration = strikeout ? Styles.TEXT_DECORATION_LINE_THROUGH
: Styles.NORMAL;
} else if (strikeout) {
decoration = decoration + " " + Styles.TEXT_DECORATION_LINE_THROUGH; //$NON-NLS-1$
}
sendRequest(addStyle(
createStyleRequest(CommandMessages.Command_ModifyFont),
Styles.TextDecoration, decoration));
}
private void changeAlignLeft() {
Request leftReq = createStyleRequest(CommandMessages.Command_TextAlignLeft);
Request request = addStyle(leftReq, Styles.TextAlign, Styles.ALIGN_LEFT);
sendRequest(request);
}
private void changeAlignCenter() {
Request centerReq = createStyleRequest(CommandMessages.Command_TextAlignCenter);
Request request = addStyle(centerReq, Styles.TextAlign,
Styles.ALIGN_CENTER);
sendRequest(request);
}
private void changeAlignRight() {
Request rightReq = createStyleRequest(CommandMessages.Command_TextAlignRight);
Request request = addStyle(rightReq, Styles.TextAlign,
Styles.ALIGN_RIGHT);
sendRequest(request);
}
private void changeTextColor(IColorSelection selection) {
changeColor(selection, Styles.TextColor,
CommandMessages.Command_ModifyTextColor);
}
private void showTempFont(IFontChooser source) {
IGraphicalViewer viewer = getActiveViewer();
if (viewer == null)
return;
TextStyle textStyle;
if (source == null) {
textStyle = null;
} else {
textStyle = new TextStyle(FontUtils.getFont(source.getFontName(),
source.getFontHeight(), source.getBold(), source
.getItalic()), ColorUtils.getColor(source
.getColor()), null);
textStyle.strikeout = source.getStrikeout();
textStyle.underline = source.getUnderline();
}
for (Object o : getSelectedElements()) {
IGraphicalPart part = getGraphicalPart(o, viewer);
if (part != null) {
IGraphicalPart p = part instanceof ITopicPart ? ((ITopicPart) part)
.getOwnerBranch()
: part;
// (ITitleTextPart) part
// .getAdapter(ITitleTextPart.class);
if (p != null) {
if (textStyle == null) {
MindMapUtils.flushCache(p, MindMapUI.CACHE_TEXT_STYLE);
} else {
MindMapUtils.setCache(p, MindMapUI.CACHE_TEXT_STYLE,
textStyle);
}
p.refresh();
}
}
}
}
}