/* ******************************************************************************
* 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.font;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.xmind.ui.color.ColorSelection;
import org.xmind.ui.color.IColorSelection;
import org.xmind.ui.color.PaletteContents;
import org.xmind.ui.color.PaletteItem;
import org.xmind.ui.color.PaletteViewer;
import org.xmind.ui.resources.FontUtils;
import org.xmind.ui.viewers.ISliderContentProvider;
import org.xmind.ui.viewers.SliderViewer;
/**
* @author briansun
*/
public class FontDialog extends Dialog implements IFontChooser {
private static class TreeArrayContentProvider extends ArrayContentProvider
implements ITreeContentProvider {
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parentElement) {
return new Object[0];
}
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
return null;
}
/**
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
return false;
}
}
private class SizeControlListener
implements ModifyListener, ISelectionChangedListener {
private boolean synchronizingSelection = false;
public void selectionChanged(SelectionChangedEvent event) {
if (synchronizingSelection)
return;
IStructuredSelection ss = (IStructuredSelection) event
.getSelection();
Object o = ss.getFirstElement();
if (o instanceof Integer) {
int v = ((Integer) o).intValue();
synchronizingSelection = true;
setFontHeight(v);
synchronizingSelection = false;
fireFontChanged();
}
}
public void modifyText(ModifyEvent e) {
if (synchronizingSelection)
return;
int height;
try {
height = Integer.parseInt(sizeText.getText());
} catch (Exception e1) {
return;
}
synchronizingSelection = true;
sizeChangedByText = true;
setFontHeight(height);
sizeChangedByText = false;
synchronizingSelection = false;
fireFontChanged();
}
}
private static final int DEFAULT_GROUP_WIDTH = SWT.DEFAULT;
private static final int DEFAULT_GROUP_HEIGHT = Util.isMac() ? 200 : 185;
private static final int MIN_FONT_HEIGHT = 5;
private static final int MAX_FONT_HEIGHT = 72;
private static String DEFAULT_FONT_NAME = null;
private static int DEFAULT_FONT_HEIGHT = SWT.DEFAULT;
private static PaletteContents DEFAULT_PALLETE = null;
private String fontName = null;
private int fontHeight = SWT.DEFAULT;
private RGB color = null;
private boolean bold = false;
private boolean italic = false;
private boolean underline = false;
private boolean strikeout = false;
private FilteredTree fontTree = null;
private Text sizeText = null;
private ListViewer sizeList = null;
private SliderViewer sizeScale = null;
private Button boldButton = null;
private Button italicButton = null;
private Button underlineButton = null;
private Button strikeoutButton = null;
private PaletteViewer paletteViewer = null;
private List<IFontChooserListener> fontDialogListeners = null;
private boolean sizeChangedByText = false;
/**
*
*/
public FontDialog(Shell parent) {
super(parent);
setShellStyle(SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
}
/**
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite p = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false)
.margins(5, 5).applyTo(p);
Group fontGroup = new Group(p, SWT.NONE);
fontGroup.setText(Messages.FamilyGroup_text);
GridLayoutFactory.swtDefaults().applyTo(fontGroup);
GridDataFactory.fillDefaults()
.hint(DEFAULT_GROUP_WIDTH, DEFAULT_GROUP_HEIGHT)
.applyTo(fontGroup);
createFontControl(fontGroup);
Group sizeGroup = new Group(p, SWT.NONE);
sizeGroup.setText(Messages.HeightGroup_text);
// GridLayoutFactory.swtDefaults().applyTo( sizeGroup );
GridDataFactory.fillDefaults()
.hint(DEFAULT_GROUP_WIDTH, DEFAULT_GROUP_HEIGHT)
.applyTo(sizeGroup);
createSizeControl(sizeGroup);
Composite typeComposite = new Composite(p, SWT.NONE);
GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(typeComposite);
GridDataFactory.fillDefaults()
.hint(DEFAULT_GROUP_WIDTH, DEFAULT_GROUP_HEIGHT)
.applyTo(typeComposite);
Group typeGroup = new Group(typeComposite, SWT.NONE);
typeGroup.setText(Messages.TypeGroup_text);
GridLayoutFactory.swtDefaults().applyTo(typeGroup);
GridDataFactory.fillDefaults().applyTo(typeGroup);
createTypeControl(typeGroup);
Group colorGroup = new Group(typeComposite, SWT.NONE);
colorGroup.setText(Messages.ColorGroup_text);
GridLayoutFactory.swtDefaults().applyTo(colorGroup);
GridDataFactory.fillDefaults().grab(true, true).applyTo(colorGroup);
createColorControl(colorGroup);
return p;
}
/**
* @param parent
*/
private void createColorControl(Group parent) {
paletteViewer = new PaletteViewer();
paletteViewer.setShowStandardLabel(false);
paletteViewer.setHasVerticalIndent(false);
paletteViewer.createControl(parent);
paletteViewer.setInput(getPaletteContents());
if (getColor() != null) {
paletteViewer.setSelection(new ColorSelection(getColor()));
}
paletteViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof IColorSelection) {
setColor(((IColorSelection) selection).getColor());
} else {
setColor(null);
}
fireFontChanged();
}
});
paletteViewer.getControl().setBackground(parent.getBackground());
}
protected PaletteContents getPaletteContents() {
return getDefaultPaletteContents();
}
private static PaletteContents getDefaultPaletteContents() {
if (DEFAULT_PALLETE == null) {
PaletteContents paletteContent = new PaletteContents(9, 3, 3);
paletteContent.addItem(PaletteItem.Red);
paletteContent.addItem(PaletteItem.Orange);
paletteContent.addItem(PaletteItem.Green);
paletteContent.addItem(PaletteItem.Blue);
paletteContent.addItem(PaletteItem.Yellow);
paletteContent.addItem(PaletteItem.Indigo);
paletteContent.addItem(PaletteItem.Purple);
paletteContent.addItem(PaletteItem.Black);
paletteContent.addItem(PaletteItem.White);
DEFAULT_PALLETE = paletteContent;
}
return DEFAULT_PALLETE;
}
/**
* @param parent
*/
private void createTypeControl(Group parent) {
boldButton = new Button(parent, SWT.CHECK);
boldButton.setText(Messages.BoldButton_text);
boldButton.setFont(JFaceResources.getFontRegistry()
.getBold(JFaceResources.DEFAULT_FONT));
boldButton.setSelection(getBold());
italicButton = new Button(parent, SWT.CHECK);
italicButton.setText(Messages.ItalicButton_text);
italicButton.setFont(JFaceResources.getFontRegistry()
.getItalic(JFaceResources.DEFAULT_FONT));
italicButton.setSelection(getItalic());
underlineButton = new Button(parent, SWT.CHECK);
underlineButton.setText(Messages.UnderlineButton_text);
underlineButton.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.drawLine(e.x + 20, e.y + e.height - 4, e.x + e.width,
e.y + e.height - 4);
}
});
underlineButton.setSelection(getUnderline());
strikeoutButton = new Button(parent, SWT.CHECK);
strikeoutButton.setText(Messages.StrikeoutButton_text);
strikeoutButton.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.drawLine(e.x + 20, e.y + e.height / 2, e.x + e.width,
e.y + e.height / 2);
}
});
strikeoutButton.setSelection(getStrikeout());
Listener listener = new Listener() {
public void handleEvent(Event event) {
setBold(boldButton.getSelection());
setItalic(italicButton.getSelection());
setUnderline(underlineButton.getSelection());
setStrikeout(strikeoutButton.getSelection());
fireFontChanged();
}
};
boldButton.addListener(SWT.Selection, listener);
italicButton.addListener(SWT.Selection, listener);
underlineButton.addListener(SWT.Selection, listener);
strikeoutButton.addListener(SWT.Selection, listener);
}
/**
* @param parent
*/
private void createSizeControl(Group parent) {
GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(false)
.applyTo(parent);
SizeControlListener listener = new SizeControlListener();
sizeText = new Text(parent, SWT.BORDER | SWT.CENTER);
GridDataFactory.fillDefaults().span(2, 1).applyTo(sizeText);
sizeText.addModifyListener(listener);
sizeList = new ListViewer(parent,
SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);
sizeList.setContentProvider(new ArrayContentProvider());
sizeList.setLabelProvider(new LabelProvider());
sizeList.setInput(Arrays.asList(8, 9, 10, 11, 12, 14, 16, 18, 20, 22,
24, 36, 48, 56, 64, 72));
int listWidthHint = Util.isMac() ? SWT.DEFAULT : 40;
GridDataFactory.fillDefaults().grab(false, true)
.hint(listWidthHint, SWT.DEFAULT)
.applyTo(sizeList.getControl());
sizeScale = new SliderViewer(parent, SWT.VERTICAL);
int scaleWidthHint = Util.isMac() ? SWT.DEFAULT : 20;
GridDataFactory.fillDefaults().grab(false, true)
.hint(scaleWidthHint, SWT.DEFAULT)
.applyTo(sizeScale.getControl());
sizeScale.setContentProvider(new ISliderContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
public void dispose() {
}
// public Object[] getValues(Object input) {
// return new Integer[] { Integer.valueOf(MIN_FONT_HEIGHT),
// Integer.valueOf(MAX_FONT_HEIGHT) };
// }
public Object getValue(Object input, double ratio) {
int value = (int) Math
.round((MAX_FONT_HEIGHT - MIN_FONT_HEIGHT) * ratio
+ MIN_FONT_HEIGHT);
return Integer.valueOf(value);
}
public double getRatio(Object input, Object value) {
int v = ((Integer) value).intValue();
return (v - MIN_FONT_HEIGHT) * 1.0d
/ (MAX_FONT_HEIGHT - MIN_FONT_HEIGHT);
}
});
sizeList.addSelectionChangedListener(listener);
sizeScale.addSelectionChangedListener(listener);
setFontHeight(getFontHeight());
}
/**
* @param parent
*/
private void createFontControl(Group parent) {
// fontTree = new FilteredTree(parent, SWT.FULL_SELECTION,
// new PatternFilter());
fontTree = new FilteredTree(parent, SWT.FULL_SELECTION,
new PatternFilter(), true);
fontTree.getViewer().setContentProvider(new TreeArrayContentProvider());
fontTree.getViewer().setInput(FontUtils.getAvailableFontNames());
setFontName(getFontName());
fontTree.getViewer()
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection sel = (IStructuredSelection) event
.getSelection();
if (sel.isEmpty()) {
setFontName(null);
} else {
setFontName((String) sel.getFirstElement());
}
fireFontChanged();
}
});
// fontTree.setEnabled(false);
// FontUtils.fetchAvailableFontNames(parent.getDisplay(),
// new IFontNameListCallback() {
// public void setAvailableFontNames(List<String> fontNames) {
// if (fontTree.isDisposed())
// return;
// fontTree.setEnabled(true);
// fontTree.getViewer().setInput(fontNames);
// setFontName(getFontName());
// fontTree.getViewer().addSelectionChangedListener(
// new ISelectionChangedListener() {
// public void selectionChanged(
// SelectionChangedEvent event) {
// IStructuredSelection sel = (IStructuredSelection) event
// .getSelection();
// if (sel.isEmpty()) {
// setFontName(null);
// } else {
// setFontName((String) sel
// .getFirstElement());
// }
// fireFontChanged();
// }
//
// });
// }
//
// });
GridDataFactory.fillDefaults().grab(true, true).hint(150, SWT.DEFAULT)
.applyTo(fontTree);
}
/**
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.FontDialog_text);
// newShell.setSize( 400, 200 );
}
/**
* @see org.eclipse.jface.dialogs.Dialog#getInitialLocation(org.eclipse.swt.graphics.Point)
*/
@Override
protected Point getInitialLocation(Point initialSize) {
Rectangle r = getParentShell().getBounds();
return new Point(r.x + r.width - initialSize.x,
r.y + r.height - initialSize.y);
}
/**
* @param listener
*/
public void addFontChooserListener(IFontChooserListener listener) {
if (fontDialogListeners == null)
fontDialogListeners = new ArrayList<IFontChooserListener>();
fontDialogListeners.add(listener);
}
/**
* @param listener
*/
public void removeFontChooserListener(IFontChooserListener listener) {
if (fontDialogListeners == null)
return;
fontDialogListeners.remove(listener);
}
/**
*
*/
protected void fireFontChanged() {
if (fontDialogListeners == null)
return;
for (final Object l : fontDialogListeners.toArray()) {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
((IFontChooserListener) l).fontChanged(FontDialog.this);
}
});
}
}
/**
* @return the color
*/
public RGB getColor() {
return color;
}
/**
* @param color
* the color to set
*/
public void setColor(RGB color) {
this.color = color;
if (paletteViewer != null && !paletteViewer.getControl().isDisposed()) {
if (color == null)
paletteViewer.setSelection(ColorSelection.EMPTY);
else
paletteViewer.setSelection(new ColorSelection(color));
}
}
/**
* @return the bold
*/
public boolean getBold() {
return bold;
}
/**
* @param bold
* the bold to set
*/
public void setBold(boolean bold) {
this.bold = bold;
if (boldButton != null && !boldButton.isDisposed()) {
boldButton.setSelection(bold);
}
}
/**
* @return the italic
*/
public boolean getItalic() {
return italic;
}
/**
* @param italic
* the italic to set
*/
public void setItalic(boolean italic) {
this.italic = italic;
if (italicButton != null && !italicButton.isDisposed()) {
italicButton.setSelection(italic);
}
}
/**
* @return the underline
*/
public boolean getUnderline() {
return underline;
}
/**
* @param underline
* the underline to set
*/
public void setUnderline(boolean underline) {
this.underline = underline;
if (underlineButton != null && !underlineButton.isDisposed()) {
underlineButton.setSelection(underline);
}
}
/**
* @return the strikeout
*/
public boolean getStrikeout() {
return strikeout;
}
/**
* @param strikeout
* the strikeout to set
*/
public void setStrikeout(boolean strikeout) {
this.strikeout = strikeout;
if (strikeoutButton != null && !strikeoutButton.isDisposed()) {
strikeoutButton.setSelection(strikeout);
}
}
/**
* @return the fontName
*/
public String getFontName() {
return fontName;
}
/**
* @param fontName
* the fontName to set
*/
public void setFontName(String fontName) {
if (fontName == null)
fontName = getDefaultFontName();
this.fontName = fontName;
if (fontTree != null && !fontTree.isDisposed()
&& fontTree.isEnabled()) {
fontTree.setInitialText(fontName);
}
}
/**
* @return the fontHeight
*/
public int getFontHeight() {
return fontHeight;
}
/**
* @param fontHeight
* the fontHeight to set
*/
public void setFontHeight(int fontHeight) {
if (fontHeight < 0)
fontHeight = getDefaultFontHeight();
this.fontHeight = fontHeight;
if (sizeText != null && !sizeText.isDisposed() && !sizeChangedByText) {
int position = -1;
if (sizeText.isFocusControl()) {
position = sizeText.getSelection().x;
}
sizeText.setText(Integer.toString(fontHeight));
if (position >= 0) {
sizeText.setSelection(
Math.min(position, sizeText.getText().length()));
}
}
if (sizeList != null && !sizeList.getControl().isDisposed()) {
sizeList.setSelection(
new StructuredSelection(Integer.valueOf(fontHeight)), true);
}
if (sizeScale != null && !sizeScale.getControl().isDisposed()) {
sizeScale.setSelection(
new StructuredSelection(Integer.valueOf(fontHeight)), true);
}
}
protected static String getDefaultFontName() {
if (DEFAULT_FONT_NAME == null)
DEFAULT_FONT_NAME = JFaceResources.getDefaultFont().getFontData()[0]
.getName();
return DEFAULT_FONT_NAME;
}
protected static int getDefaultFontHeight() {
if (DEFAULT_FONT_HEIGHT < 0)
DEFAULT_FONT_HEIGHT = JFaceResources.getDefaultFont()
.getFontData()[0].getHeight();
return DEFAULT_FONT_HEIGHT;
}
/**
* @param fd
*/
public void setInitialFont(FontData fd) {
setFontName(fd.getName());
setFontHeight(fd.getHeight());
setBold((fd.getStyle() & SWT.BOLD) != 0);
setItalic((fd.getStyle() & SWT.ITALIC) != 0);
}
}