自定义RCP外观

如果说只需要改变RCP的皮肤可以参照IBM上的Eclipse程序界面美化技术
[url]http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-rcprich/[/url]
如果想自定义RCP的外观就得用到presentationFactories,presentationFactories是eclipse为editor以及view提供的一个外观工厂,在eclipse官网上推荐的书中就提到过这么个工厂,今天再看MP3MANAGER源代码的时候发现实现起来也挺简单的,不过我还是习惯eclipse风格,所以没将应用的外观改变,之前也一直在寻找改变RCP外观的方法,昨天网友告诉我IBM上有我就去看了下,就是简单的变换了图片和背景颜色,也就是个SWT的皮肤而已,下面我就直接贴代码演示presentationFactories的实现方法
首先就是Presentation 类:
/*******************************************************************************
* Copyright (c) 2009 Siemens AG
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kai T枚dter - initial API and implementation
*******************************************************************************/

package com.siemens.ct.mp3m.ui.presentation;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;

public class Presentation extends StackPresentation {

private Color borderColor;

private IPresentablePart current;

private final PaintListener paintListener = new PaintListener() {

public void paintControl(final PaintEvent e) {
final Rectangle clientArea = presentationControl.getClientArea();
// Image img = new Image(e.display, clientArea.width,
// clientArea.height);
// GC gc = new GC(img);
final GC gc = e.gc;

final int border = 1;
gc.setLineWidth(border);
gc.setForeground(borderColor);
gc.drawRectangle(clientArea.x, clientArea.y, clientArea.width - border,
clientArea.height - border);

// e.gc.drawImage(img, 0, 0);
// gc.dispose();
// img.dispose();

}
};

/**
* Listener attached to all child parts. It responds to changes in part
* properties
*/
private final IPropertyListener partPropertyChangeListener = new IPropertyListener() {

public void propertyChanged(final Object source, final int property) {

if (source instanceof IPresentablePart) {
redraw();
}
}
};

private Composite presentationControl;

private TabContainer tabContainer;

private Title titleBar;

private Color toolBarColor;

public Presentation(final Composite parent, final IStackPresentationSite site) {
super(site);
// Create a top-level control for the presentation.
presentationControl = new Composite(parent, SWT.NONE);
borderColor = new Color(presentationControl.getDisplay(), 50, 50, 50);
toolBarColor = new Color(presentationControl.getDisplay(), 203, 220, 235);

presentationControl.addPaintListener(paintListener);

titleBar = new Title(presentationControl, SWT.NONE, getSite());
tabContainer = new TabContainer(presentationControl, SWT.NONE);

/*
* Add a dispose listener. Important because dispose() may // not always
* be called.
*/
presentationControl.addDisposeListener(new DisposeListener() {

public void widgetDisposed(final DisposeEvent e) {
presentationDisposed();
}
});

}

protected Presentation(final IStackPresentationSite stackSite) {
super(stackSite);
// TODO Auto-generated constructor stub
}

@Override
public void addPart(final IPresentablePart newPart, final Object cookie) {
newPart.addPropertyListener(partPropertyChangeListener);
tabContainer.addPart(newPart, this, getSite());
}

@Override
public int computePreferredSize(final boolean width, final int availableParallel,
final int availablePerpendicular, final int preferredResult) {
if (width) {
return Math.max(preferredResult, 100);
} else {
return tabContainer.getHeight() + titleBar.getHeight();
}
}

@Override
public void dispose() {
presentationDisposed();
}

@Override
public StackDropResult dragOver(final Control currentControl, final Point location) {
// TODO Auto-generated method stub
return null;
}

/**
* Gets the colorBorder.
*
* @return Returns the colorBorder.
*/
public Color getColorBorder() {
return borderColor;
}

@Override
public Control getControl() {
return presentationControl;
}

@Override
public Control[] getTabList(final IPresentablePart part) {
return new Control[] { part.getControl() };
}

@Override
public void removePart(final IPresentablePart oldPart) {
oldPart.removePropertyListener(partPropertyChangeListener);
tabContainer.removePart(oldPart);
titleBar.removePart(oldPart);
if (current == oldPart) {
current = null;
}
redraw();
}

@Override
public void selectPart(final IPresentablePart toSelect) {
// Ignore redundant selections
if (toSelect == current) {
return;
}

// If there was an existing part selected, make it invisible
if (current != null) {
current.setVisible(false);
}
// Select the new part
current = toSelect;

// Make the part visible before setBounds, or the call to setBounds
// may be ignored.
if (current != null) {
current.setVisible(true);
setBounds(presentationControl.getBounds());
titleBar.setPresentablePart(current);
tabContainer.setPresentablePart(current);
}
}

@Override
public void setActive(final int newState) {
// TODO Auto-generated method stub

}

@Override
public void setBounds(final Rectangle bounds) {
// Set the bounds of the presentation widget
presentationControl.setBounds(bounds);

final int titlebarHeight = titleBar.getHeight();
final Rectangle clientArea = presentationControl.getClientArea();
titleBar
.setBounds(clientArea.x + 1, clientArea.y + 1, clientArea.width - 2, titlebarHeight);
final int tabPaneHeight = tabContainer.getHeight();
tabContainer.setBounds(clientArea.x, clientArea.y + clientArea.height - tabPaneHeight,
clientArea.width, tabPaneHeight);
if (current != null) {
final Rectangle contentArea = presentationControl.getBounds();
int toolBarHeight = 0;
final Control toolBar = current.getToolBar();
if (toolBar != null) {
toolBar.setBackground(toolBarColor);
toolBarHeight = toolBar.getBounds().height;
toolBar.setBounds(clientArea.x + 1, clientArea.y + 1 + titlebarHeight,
clientArea.width - 2, toolBarHeight);
}
contentArea.x += 1;
contentArea.y += titlebarHeight + toolBarHeight;
contentArea.width -= 2;
contentArea.height -= titlebarHeight + tabPaneHeight + toolBarHeight;
if (tabPaneHeight == 0) {
contentArea.height -= 1;
}
current.setBounds(contentArea);
}
}

@Override
public void setState(final int state) {
// TODO Auto-generated method stub

}

@Override
public void setVisible(final boolean isVisible) {
// Make the presentation widget visible
presentationControl.setVisible(isVisible);
titleBar.setVisible(isVisible);

// Make the currently visible part visible
if (current != null) {
current.setVisible(isVisible);

if (isVisible) {
// Restore the bounds of the currently visible part.
// IPartPresentations can be used by multiple
// StackPresentations,
// although only one such presentation is ever visible at a
// time.
// It is possible that some other presentation has changed the
// bounds of the part since it was last visible, so we need to
// update the part's bounds when the presentation becomes
// visible.

setBounds(presentationControl.getBounds());
}
}
}

@Override
public void showPaneMenu() {
// TODO Auto-generated method stub
}

@Override
public void showSystemMenu() {
// TODO Auto-generated method stub
}

protected void presentationDisposed() {
// Remove any listeners that were attached to any
// global Eclipse resources. This is necessary in order to prevent
// memory leaks.
borderColor.dispose();
toolBarColor.dispose();
presentationControl.removePaintListener(paintListener);
presentationControl.dispose();
presentationControl = null;
}

protected void redraw() {
if (presentationControl != null) {
presentationControl.redraw();
titleBar.redraw();
tabContainer.redraw();
}
}
}

然后就是生产Presentation 的工厂:
/*******************************************************************************
* Copyright (c) 2009 Siemens AG
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kai T枚dter - initial API and implementation
*******************************************************************************/

package com.siemens.ct.mp3m.ui.presentation;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.presentations.AbstractPresentationFactory;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackPresentation;

public class PresentationFactory extends AbstractPresentationFactory {
public StackPresentation createEditorPresentation(Composite parent, IStackPresentationSite site) {
return new Presentation(parent, site);
}

public StackPresentation createViewPresentation(Composite parent, IStackPresentationSite site) {
return new Presentation(parent, site);
}

public StackPresentation createStandaloneViewPresentation(Composite parent,
IStackPresentationSite site, boolean showTitle) {
return new Presentation(parent, site);
}
}

重要类:
package com.netunit.workbench.presentation;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.presentations.IPresentablePart;

import com.netunit.workbench.Activator;
import com.netunit.workbench.intro.Application;

/**
* 抽象皮肤属性
* @author Ming.He
*
*/
public abstract class AbstractClosable extends Canvas implements PaintListener {

protected static Image closeUnselectedImage; //未选中close时的图片
protected static Image closeSelectedImage; //选中close时的图片
protected boolean isCloseSelected; //close是否被选中
protected boolean isMouseOver; //鼠标是否点中

protected IPresentablePart part; //控制view和editor的皮肤

private final MouseMoveListener mouseMoveListener = new MouseMoveListener(){

@Override
public void mouseMove(MouseEvent e) {
boolean oldState = isCloseSelected;
Rectangle clientArea = getBounds();
clientArea.x = clientArea.width - 20;
clientArea.width = closeSelectedImage.getBounds().width;
clientArea.y = 2;
clientArea.height = closeSelectedImage.getBounds().height;
if(clientArea.contains(e.x, e.y)){
isCloseSelected = true;
}else{
isCloseSelected = false;
}

if(oldState != isCloseSelected){
redraw();
}
}

};

protected MouseTrackAdapter mouseTrackAdapter = new MouseTrackAdapter(){

@Override
public void mouseEnter(MouseEvent e) {
isMouseOver = true;
redraw();
}

@Override
public void mouseExit(MouseEvent e) {
isMouseOver = false;
isCloseSelected = false;
redraw();
}

};

static{
ImageDescriptor imageDescriptor = Activator.imageDescriptorFromPlugin(Application.ID, "icons/close.gif");
if(null != imageDescriptor){
closeUnselectedImage = imageDescriptor.createImage();
}
imageDescriptor = Activator.imageDescriptorFromPlugin(Application.ID, "icons/closeSelected.gif");
if(null != imageDescriptor){
closeSelectedImage = imageDescriptor.createImage();
}
}

public AbstractClosable(Composite parent, int style) {
super(parent, style);
addMouseMoveListener(mouseMoveListener);
addMouseTrackListener(mouseTrackAdapter);
}

public void setPresentablePart(IPresentablePart part){
this.part = part;
setToolTipText(part.getTitleToolTip());
layout();
redraw();
}

public int getHeight(){
return 21;
}

public void removePart(IPresentablePart oldPart){
if(oldPart == part){
part = null;
}
}

protected String shortenText(GC gc, String text, int width){
if(null == text){
return null;
}
if(gc.textExtent(text, 0).x <= width){
return text;
}
String eclipse = "...";
int eclipseWidth = gc.textExtent(eclipse, 0).x;
int textLength = text.length();

while(textLength >= 0){
String s1 = text.substring(0, textLength);
int textWidth = gc.textExtent(s1, 0).x;

if(textWidth + eclipseWidth < width){
text = s1 + eclipse;
break;
}
textLength --;
}
return text;
}

}

辅助类:
/*******************************************************************************
* Copyright (c) 2009 Siemens AG
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kai T枚dter - initial API and implementation
*******************************************************************************/

package com.siemens.ct.mp3m.ui.presentation;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;

public class TabContainer extends Composite {

protected List<Tab> tabItems = new ArrayList<Tab>();

protected IPresentablePart part;

protected int style;

public TabContainer(Composite parent, int style) {
super(parent, style);
this.style = style;
}

public void addPart(IPresentablePart part, Presentation presentation,
IStackPresentationSite site) {
Tab tab = new Tab(this, style, presentation, site);
tab.setPresentablePart(part);
tabItems.add(tab);
redraw();
}

public void setPresentablePart(IPresentablePart part) {
this.part = part;
for (Tab b : tabItems) {
b.setSected(b.checkPart(part));
}
redraw();
}

public int getHeight() {
if (tabItems.size() < 2) {
return 0;
}
return tabItems.size() * tabItems.get(0).getHeight() - tabItems.size() + 1;
}

@Override
public void setBounds(int x, int y, int width, int height) {
int y2 = 0;
int h = 21;
for (Tab b : tabItems) {
b.setBounds(x, y2, width, h);
y2 += 20;
}
super.setBounds(x, y, width, height);
}

public void redraw() {
if (tabItems.size() < 2) {
return;
}
for (Tab b : tabItems) {
b.redraw();
}
}

public void removePart(IPresentablePart oldPart) {
Tab foundTab = null;
for (Tab b : tabItems) {
if (b.getPart() == oldPart) {
foundTab = b;
break;
}
}
if (foundTab != null) {
tabItems.remove(foundTab);
foundTab.dispose();
}
}
}

/*******************************************************************************
* Copyright (c) 2009 Siemens AG
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kai T枚dter - initial API and implementation
*******************************************************************************/

package com.siemens.ct.mp3m.ui.presentation;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;

public class Tab extends AbstractClosable implements PaintListener {

private final Presentation presentation;

private final IStackPresentationSite site;

protected final Color unselectedTop = new Color(getDisplay(), 250, 250, 250);

protected final Color unselectedBottom = new Color(getDisplay(), 200, 225, 255);

protected final Color selectedTop = new Color(getDisplay(), 250, 230, 150);

protected final Color selectedBottom = new Color(getDisplay(), 240, 155, 30);

protected final Color mouseOverTop = new Color(getDisplay(), 255, 248, 223);

protected final Color mouseOverBottom = new Color(getDisplay(), 255, 225, 120);

protected Font font = new Font(getDisplay(), "Default", 10, SWT.NORMAL);

private boolean isSelected;

/**
* This listener responds to selection events in all tabs.
*/
private final MouseListener mouseListener = new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (part != null) {
part.setFocus();
if (isCloseSelected()) {
site.close(new IPresentablePart[] { part });
} else {
site.selectPart(part);
presentation.selectPart(part);
}
}
}
};

public Tab(Composite parent, int style, Presentation presentation, IStackPresentationSite site) {
super(parent, style | SWT.NO_BACKGROUND);
this.presentation = presentation;
this.site = site;

setSected(false);
addPaintListener(this);
addMouseListener(mouseListener);
}

@Override
public void setPresentablePart(IPresentablePart part) {
this.part = part;
setToolTipText(part.getTitleToolTip());
layout();
redraw();
}

public boolean checkPart(IPresentablePart part) {
return (this.part == part);
}

public void setSected(boolean selected) {
isSelected = selected;
}

/**
* Paint the title bar
*/
public void paintControl(PaintEvent e) {
Rectangle clientArea = getBounds();
Image img = new Image(e.display, clientArea.width, clientArea.height);
GC gc = new GC(img);

gc.setForeground(presentation.getColorBorder());
gc.drawRectangle(0, 0, clientArea.width - 1, clientArea.height - 1);

Color colorTop;
Color colorBottom;

if (isMouseOver) {
if (isSelected) {
colorTop = selectedBottom;
colorBottom = selectedTop;
} else {
colorTop = mouseOverTop;
colorBottom = mouseOverBottom;
}
} else {
if (isSelected) {
colorTop = selectedTop;
colorBottom = selectedBottom;
} else {
colorTop = unselectedTop;
colorBottom = unselectedBottom;
}
}
gc.setForeground(colorTop);
gc.setBackground(colorBottom);
gc.fillGradientRectangle(1, 1, clientArea.width - 2, clientArea.height - 2, true);

if (part != null) {
Image partImage = part.getTitleImage();
gc.drawImage(partImage, 2, 2);

Color colorText = new Color(getDisplay(), 0, 0, 0);
// gc.setFont(font);
gc.setForeground(colorText);
String dirty = "";
if (part.isDirty()) {
dirty = "*";
}
int closeImageOffset = 0;
if (part.isCloseable()) {
closeImageOffset = 20;
}
String text = shortenText(gc, dirty + part.getTitle(), clientArea.width - 25
- closeImageOffset);
gc.drawText(text, partImage.getBounds().width + 7, 3, true);
}

if (part.isCloseable()) {
if (isCloseSelected) {
gc.drawImage(closeSelectedImage, clientArea.width - 20, 3);
} else {
gc.drawImage(closeUnselectedImage, clientArea.width - 20, 3);
}
}

e.gc.drawImage(img, 0, 0);
gc.dispose();
img.dispose();
}

public IPresentablePart getPart() {
return part;
}

public boolean isCloseSelected() {
return isCloseSelected;
}

/*
* (non-Javadoc)
*
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
@Override
public void dispose() {
unselectedTop.dispose();
unselectedBottom.dispose();
selectedTop.dispose();
selectedBottom.dispose();
mouseOverTop.dispose();
mouseOverBottom.dispose();
font.dispose();
super.dispose();
}
}

/*******************************************************************************
* Copyright (c) 2009 Siemens AG
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kai T枚dter - initial API and implementation
*******************************************************************************/

package com.siemens.ct.mp3m.ui.presentation;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;

public class Title extends AbstractClosable {
private IStackPresentationSite site;

Color colorTop = new Color(getDisplay(), 135, 135, 135);

Color colorBottom = new Color(getDisplay(), 50, 50, 50);

Color colorText = new Color(getDisplay(), 255, 255, 255);

protected Font font = new Font(getDisplay(), "Default", 10, SWT.BOLD);

/**
* This listener responds to selection events in all tab buttons.
*/
private MouseListener mouseListener = new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if (part != null) {
part.setFocus();
if (isCloseSelected) {
site.close(new IPresentablePart[] { part });
}
}
}
};

public Title(Composite parent, int style, IStackPresentationSite site) {
super(parent, style | SWT.NO_BACKGROUND);
this.site = site;
addPaintListener(this);
addMouseListener(mouseListener);
}

/**
* Paint the title
*/
public void paintControl(PaintEvent e) {
Rectangle clientArea = getBounds();
Image img = new Image(e.display, clientArea.width, clientArea.height);
GC gc = new GC(img);

gc.setForeground(colorTop);
gc.setBackground(colorBottom);
gc.fillGradientRectangle(0, 0, clientArea.width, clientArea.height, true);

if (part != null) {
gc.setFont(JFaceResources.getBannerFont());
gc.setForeground(colorText);
String dirty = "";
if (part.isDirty()) {
dirty = "*";
}
String text = shortenText(gc,dirty + part.getTitle(), clientArea.width - 30);
gc.drawText(text, 5, 2, true);

if (part.isCloseable()) {
if (isCloseSelected) {
gc.drawImage(closeSelectedImage, clientArea.width - 20, 2);
} else {
gc.drawImage(closeUnselectedImage, clientArea.width - 20, 2);
}
}
}

e.gc.drawImage(img, 0, 0);
gc.dispose();
img.dispose();
}

/*
* (non-Javadoc)
*
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
@Override
public void dispose() {
colorTop.dispose();
colorBottom.dispose();
colorText.dispose();
font.dispose();
super.dispose();
}

}


在plugin.xml中加入
 <extension
point="org.eclipse.ui.presentationFactories">
<factory
class="com.siemens.ct.mp3m.ui.presentation.PresentationFactory"
id="com.siemens.ct.mp3m.ui.presentation.PresentationFactory"
name="Siemens CT Presentation"/>
</extension>

然后在plugin_customization.ini和presentation.ini文件中加入
org.eclipse.ui/presentationFactoryId=com.siemens.ct.mp3m.ui.presentation.PresentationFactory

代码不难摘自MP3M,相信大家能理解,建议大家将这几个类放到自己的UI.PRESENTATION插件中,方便重复调用,最后提醒大家一点,就是如果你设置视图标题栏的弧线形外观,那么你上面的都是无用功了,不会出来效果的 :P
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值