@@ -9,13 +9,9 @@

import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.CursorLinePainter;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TypedListener;
@@ -41,9 +37,7 @@ protected CommonMergeViewer(Composite parent, CompareConfiguration configuration
@Override
protected void configureTextViewer(final TextViewer textViewer)
{
setBackgroundColor(getCurrentTheme().getBackground());
setForegroundColor(getCurrentTheme().getForeground());
setSelectionColors(textViewer);
ThemePlugin.getDefault().getControlThemerFactory().apply(textViewer);

// Force line highlight color. We need to perform this after the line painter is attached, which happens after
// the return of this method. Scheduling async seems to work.
@@ -84,25 +78,6 @@ protected String getDocumentPartitioning()
return IDocumentExtension3.DEFAULT_PARTITIONING;
}

private void setSelectionColors(TextViewer sourceViewer)
{
// TODO Combine with code from ThemeableEditorExtension
// Force selection color
StyledText textWidget = sourceViewer.getTextWidget();
Color existingSelectionBG = textWidget.getSelectionBackground();
RGB selectionRGB = getCurrentTheme().getSelectionAgainstBG();
if (!existingSelectionBG.getRGB().equals(selectionRGB))
{
textWidget.setSelectionBackground(getColorManager().getColor(selectionRGB));
}

if (!Platform.OS_MACOSX.equals(Platform.getOS()))
{
// Linux and windows need selection fg set or we just see a block of color.
textWidget.setSelectionForeground(getColorManager().getColor(getCurrentTheme().getForeground()));
}
}

protected Theme getCurrentTheme()
{
return getThemeManager().getCurrentTheme();
@@ -15,7 +15,6 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
@@ -27,9 +26,6 @@
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.editors.text.EditorsUI;
@@ -50,7 +46,6 @@
import com.aptana.formatter.ui.IFormatterModifyDialogOwner;
import com.aptana.formatter.ui.util.IStatusChangeListener;
import com.aptana.theme.ColorManager;
import com.aptana.theme.IThemeManager;
import com.aptana.theme.ThemePlugin;

public abstract class AbstractFormatterPreferencePage extends AbstractConfigurationBlockPropertyAndPreferencePage
@@ -174,8 +169,7 @@ private ProjectionViewer createPreviewViewer(Composite parent, IVerticalRuler ve
{
ProjectionViewer viewer = new ProjectionViewer(parent, verticalRuler, overviewRuler,
showAnnotationsOverview, styles);
setFont(viewer, JFaceResources.getTextFont());
setBackgroundColor(viewer);
ThemePlugin.getDefault().getControlThemerFactory().apply(viewer);
return viewer;
}

@@ -200,35 +194,6 @@ protected Job[] createBuildJobs(IProject project)
{
return NO_BUILD_JOBS;
}

/**
* Sets the background color according to the active Theme
*
* @param viewer
*/
private void setBackgroundColor(ISourceViewer sourceViewer)
{
ColorManager colorManager = ThemePlugin.getDefault().getColorManager();
IThemeManager themeManager = ThemePlugin.getDefault().getThemeManager();
Color color = colorManager.getColor(themeManager.getCurrentTheme().getBackground());
StyledText styledText = sourceViewer.getTextWidget();
styledText.setBackground(color);
}

/**
* Sets the font for the given viewer sustaining selection and scroll position.
*
* @param sourceViewer
* the source viewer
* @param font
* the font
*/
private void setFont(ISourceViewer sourceViewer, Font font)
{
StyledText styledText = sourceViewer.getTextWidget();
styledText.setFont(font);
}

}

protected AbstractOptionsBlock createOptionsBlock(IStatusChangeListener newStatusChangedListener, IProject project,
File renamed without changes.
File renamed without changes.
@@ -10,6 +10,7 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.plugin.AbstractUIPlugin;
@@ -29,6 +30,9 @@
public class ThemePlugin extends AbstractUIPlugin
{

public static final String IBEAM_BLACK = "/icons/ibeam-black.gif"; //$NON-NLS-1$
public static final String IBEAM_WHITE = "/icons/ibeam-white.gif"; //$NON-NLS-1$

/**
* This listens for changes to the editor FG/BG/line highlight/selection colors from Eclipse's pref page. if
* invasive theming is on, we'll apply changes onto our current Aptana theme.
@@ -215,6 +219,13 @@ public void stop(BundleContext context) throws Exception
}
}

@Override
protected void initializeImageRegistry(ImageRegistry reg)
{
reg.put(IBEAM_BLACK, imageDescriptorFromPlugin(PLUGIN_ID, IBEAM_BLACK));
reg.put(IBEAM_WHITE, imageDescriptorFromPlugin(PLUGIN_ID, IBEAM_WHITE));
}

/**
* Returns the shared instance
*
@@ -11,6 +11,8 @@
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
@@ -175,6 +177,23 @@ public void apply(Viewer viewer)
}
themer.apply();
}
if (viewer instanceof TextViewer)
{
// If a themer already exists for the control, just return it
IControlThemer themer = themers.get(viewer.getControl());
if (themer != null)
{
return;
}

// No themer exists, create a new one
themer = new TextViewerThemer((TextViewer) viewer);
synchronized (themers)
{
themers.put(viewer.getControl(), themer);
}
themer.apply();
}
else
{
apply(viewer.getControl());
@@ -14,7 +14,6 @@

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
@@ -40,8 +39,6 @@
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.search.ui.text.AbstractTextSearchViewPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
@@ -1230,19 +1227,7 @@ protected void overrideSelectionColor(AbstractTextEditor editor)
return;
}

// Force selection color
StyledText textWidget = sourceViewer.getTextWidget();
Color existingSelectionBG = textWidget.getSelectionBackground();
RGB selectionRGB = getCurrentTheme().getSelectionAgainstBG();
if (!existingSelectionBG.getRGB().equals(selectionRGB))
{
textWidget.setSelectionBackground(getColorManager().getColor(selectionRGB));
}
if (!Platform.OS_MACOSX.equals(Platform.getOS()))
{
// Linux and windows need selection fg set or we just see a block of color.
textWidget.setSelectionForeground(getColorManager().getColor(getCurrentTheme().getForeground()));
}
ThemePlugin.getDefault().getControlThemerFactory().apply((Viewer) sourceViewer);
}

protected ColorManager getColorManager()
@@ -0,0 +1,210 @@
/**
* Aptana Studio
* Copyright (c) 2005-2012 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.theme.internal;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Caret;
import org.eclipse.swt.widgets.Display;

import com.aptana.theme.ThemePlugin;
import com.aptana.ui.util.UIUtils;

/**
* Applies theme colors to an ITextViewer's StyledText widget.
*
* @author cwilliams
*/
public class TextViewerThemer extends ControlThemer
{

private static final RGB BLACK = new RGB(0, 0, 0);

private Image fCaretImage;
private RGB fCaretColor;
private Cursor fCursor;

public TextViewerThemer(ITextViewer viewer)
{
super(viewer.getTextWidget());
}

protected boolean invasiveThemesEnabled()
{
return true;
}

protected boolean useEditorFont()
{
return true;
}

@Override
protected void applyTheme()
{
super.applyTheme();

if (invasiveThemesEnabled() && !controlIsDisposed())
{
overrideSelectionColor();
overrideCursor();
overrideCaretColor();
}
}

private StyledText getTextWidget()
{
return (StyledText) getControl();
}

private void overrideSelectionColor()
{
if (getTextWidget() == null)
{
return;
}

// Force selection color
Color existingSelectionBG = getTextWidget().getSelectionBackground();
RGB selectionRGB = getCurrentTheme().getSelectionAgainstBG();
if (!existingSelectionBG.getRGB().equals(selectionRGB))
{
getTextWidget().setSelectionBackground(getColorManager().getColor(selectionRGB));
}

if (!Platform.OS_MACOSX.equals(Platform.getOS()))
{
// Linux and windows need selection fg set or we just see a block of color.
getTextWidget().setSelectionForeground(getForeground());
}
}

private void overrideCursor()
{
if (getTextWidget() == null)
{
return;
}

Image cursorImage = null;
if (getCurrentTheme().hasDarkBG())
{
cursorImage = UIUtils.getImage(ThemePlugin.getDefault(), ThemePlugin.IBEAM_WHITE);
}
else
{
cursorImage = UIUtils.getImage(ThemePlugin.getDefault(), ThemePlugin.IBEAM_BLACK);
}

Display display = getTextWidget().getDisplay();
Cursor oldCursor = fCursor;

fCursor = new Cursor(display, cursorImage.getImageData(), 7, 11);
getTextWidget().setCursor(fCursor);

if (oldCursor != null)
{
oldCursor.dispose();
}
}

private void overrideCaretColor()
{
if (getTextWidget() == null)
{
return;
}

RGB caretColor = getCurrentTheme().getCaret();
if (caretColor == null)
{
return;
}

Caret caret = getTextWidget().getCaret();
// This is an ugly hack. Setting a black image doesn't work for some reason, but setting no image will cause it
// to be black.
if (caretColor.equals(BLACK))
{
caret.setImage(null);
return;
}

// Shortcut for when color is same, don't do any heavy lifting
if (this.fCaretImage != null && fCaretColor.equals(caretColor))
{
return;
}

int x = caret.getSize().x;
int y = caret.getSize().y;
// Apparently the current caret may have invalid sizings
// that will cause errors when an attempt to
// change the color is made. So perform the check and catch
// errors and exceptions so caret coloring
// doesn't affect opening the editor.
if (x > 0 && y > 0)
{
try
{
PaletteData data;
if (getThemeManager().getCurrentTheme().hasDarkBG())
{
data = new PaletteData(new RGB[] { caretColor });
}
else
{
RGB inverted = new RGB(255 - caretColor.red, 255 - caretColor.green, 255 - caretColor.blue);
data = new PaletteData(new RGB[] { inverted });
}
ImageData iData = new ImageData(x, y, 1, data);
caret.setImage(null);
if (this.fCaretImage != null)
{
this.fCaretImage.dispose();
this.fCaretImage = null;
}
this.fCaretImage = new Image(caret.getDisplay(), iData);
caret.setImage(this.fCaretImage);
fCaretColor = caretColor;
}
catch (Error e)
{
}
catch (Exception e)
{
}
}
}

@Override
public void dispose()
{
if (fCursor != null)
{
fCursor.dispose();
fCursor = null;
}

if (fCaretImage != null)
{
fCaretImage.dispose();
fCaretImage = null;
}
fCaretColor = null;

super.dispose();
}
}
@@ -20,7 +20,10 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
@@ -35,6 +38,7 @@
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.services.IEvaluationService;

@@ -332,4 +336,26 @@ private static boolean showPromptDialogUI(String title, String message)
{
return MessageDialog.openQuestion(getActiveWorkbenchWindow().getShell(), title, message);
}

public static Image getImage(AbstractUIPlugin plugin, String path)
{
ImageRegistry registry = plugin.getImageRegistry();
Image image = registry.get(path);
if (image == null)
{
ImageDescriptor id = getImageDescriptor(plugin.getBundle().getSymbolicName(), path);
if (id == null)
{
return null;
}
registry.put(path, id);
image = registry.get(path);
}
return image;
}

public static ImageDescriptor getImageDescriptor(String pluginId, String path)
{
return AbstractUIPlugin.imageDescriptorFromPlugin(pluginId, path);
}
}
@@ -13,6 +13,7 @@
import org.eclipse.swt.graphics.Image;

import com.aptana.editor.common.CommonEditorPlugin;
import com.aptana.ui.util.UIUtils;

/**
* CompletionProposalTest
@@ -30,7 +31,7 @@ protected void setUp() throws Exception
{
super.setUp();

image = CommonEditorPlugin.getImage("icons/proposal.png");
image = UIUtils.getImage(CommonEditorPlugin.getDefault(), "icons/proposal.png");
}

public void testProposalsAreEqual()