Sonntag, 18. Dezember 2011

Eclipse RCP - MessageBox

Wie erhalte ich eine MessageBox und wie setze ich die MessageBox ein?

Ein sehr gutes MessageBox Beispiel findet ihr bei www.java2s.com Die entscheidende Stelle hier nochmal kurz als Codesnippet:

MessageBox messageBox = 
  new MessageBox(shell, 
            SWT.ICON_WARNING | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
        
messageBox.setText("Warning");
messageBox.setMessage("Save the changes before exiting?");
int buttonID = messageBox.open();

Quelle: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/MessageBoxExample.htm

Der zweite Parameter der MessageBox steuert die Anzahl und Art der Buttons die in der MessageBox angezeigt werden. Weiterhin kann mit dem zweiten Paremeter der Typ der MessageBox (hier Warnung) bestimmt werden.

Die MessageBox wird modal aufgerufen. Die Methode open() öffnet die MessageBox. Am Rückgabewert kann identifiziert werden, welcher Button vom Benutzer gedrückt wurde.

Die buttonId kann mit dafür vorgesehenen Konstanten der Klasse SWT verglichen werden, z.B. if ( buttonID == SWT.CANCEL ) { ...

Die aufgeführte Liste zeigt einige Konstanten für die Buttons:

  • SWT.ABORT
  • SWT.CANCEL
  • SWT.IGNORE
  • SWT.NO
  • SWT.OK
  • SWT.RETRY
  • SWT.YES

Freitag, 25. November 2011

Eclipse RCP - Hintergrundfarbe und Image eines Labels im TreeViewer

Dieser Artikel beschreibt wie die Hintergrundfarbe eines Labels in einem TreeViewer geändert werden kann.

Das Aussehen eines Knotens in einem TreeViewer wird mit einem LabelProvider gesteuert. Der LabelProvider wird mit der Methode setLabelProvider der Klasse TreeViewer gesetzt.


// deklaration des TreeViewers in einer View Klasse 
public TreeViewer viewer;

...
// createPartControl Methode der View Klasse 
public void createPartControl(Composite parent) { 

...

  viewer.setLabelProvider(new ViewLabelProvider());

...
}

Die Aufgaben des LabelProviders werden von den geerbten Klassen bzw. den implementierten Interfaces bestimmt. Die Klasse LabelProvider bietet die Methoden getText und getImage, mit denen der Text und das Bild bestimmt werden können. Der Übergabeparameter obj vom Typ Object ist das TreeElement, dass einen Knoten im Tree repräsentiert.

In der hier gezeigten Implementierung liefert der Parameter obj den Text der im Label angezeigt wird, bzw. das Image das zum Label angezeigt wird. Würde man in der Methode getImage immer das gleiche Bild zurückgeben, dann würde der TreeViewer das gleiche Bild für alle Knoten anzeigen.

import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;

class ViewLabelProvider extends LabelProvider implements IColorProvider {

 @Override
 public String getText(Object obj) {
     return obj.toString();
 }
 
 @Override
 public Image getImage(Object obj) {
     Image img = ((TreeObject)obj).getIcon();
     return img; 
 }

 @Override
 public Color getForeground(Object element) {
     return new Color(PlatformUI.getWorkbench().getDisplay(),
                      new RGB(255,255,255));
 }

  @Override
  public Color getBackground(Object element) {
    return new Color(PlatformUI.getWorkbench().getDisplay(), 
                     new RGB(100,100,100));
  }
}

Die Methoden getForeground und getBackground bestimmen die Schriftfarbe und die Hintergrundfarbe.

Es sollte beachtet werden, dass Bilder und Farben in einer Eclipse RCP Applikation verwaltet werden sollten. Das bedeutet, dass einmal erstellte Farben und Bilder wieder freigegeben werden sollten. Mehr dazu im Bilder verwalten Artikel und im Artikel zur Farbverwaltung

Samstag, 5. November 2011

Eclipse RCP / SWT - Einfaches TreeViewer Beispiel

Eclipse 3.7 Indigo

In diesem Artikel wird ein einfaches TreeViewer Beispiel gezeigt. Das Beispiel konzentriert sich nur auf das Anzeigen eines Baumes, wodurch alle anderen Aspekte wie Menüs, andere ViewPart Elemente und andere GUI Elemente vernachlässigt werden. Es wird ein unendlicher binärer Baum dargestellt, dessen Hierarchierstufen gezählt werden. Alle notwendigen Schritte werden in einem HandsOn Tutorial nachvollzogen.

Schritt 1: RCP Applikation mit dem Namen com.blogspot.javadingsda.easytreeviewer aus der Vorlage 'RCP application with a view' erstellen.

Schritt 2: Entferne alle inneren Klassen, Methoden und Attribute aus der View Klasse und ersetze sie durch den unten aufgeführten Code. Die View Klasse sollte wie folgt aussehen.

package com.blogspot.javadingsda.easytreeviewer;

import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
  public static final String ID = 
    "com.blogspot.javadingsda.easytreeviewer.view";
  private TreeViewer treeViewer; 

  public void createPartControl(Composite parent) {
    treeViewer = new TreeViewer(parent);
    treeViewer.setContentProvider(new TreeContentProvider());
    treeViewer.setInput(new MyTreeNode(0));
  }

  public void setFocus() {
  }
}

Um mit den darzustellenden Daten versorgt zu werden, benötigt der TreeViewer eine Klasse, die das Interface ITreeContentProvider implementiert. Die Methoden des ITreeContentProvider werden im Posting ITreeContentProvider Methoden beschrieben. Für unser Beispiel sind die Methoden hasChildren(Object parent), getChildren(Object parent), getParent(Object child) und getElements(Object parent)wichtig. Die Funktionsweise der Methoden wird weiter unten in Bezug auf unser Beispiel näher erläutert. In unserem Beispiel implementiert die Klasse ViewContentProvider dieses Interface und wird dem TreeViewer mit der Methode setContntProvider(IContentProvider provider) bekannt gemacht.
Die Methode setInput(Object input) initialiseirt den Baum mit dem Root Knoten. Dieser wird nicht angezeigt.

Schritt 3: Erstelle die Klase MyTreeNode.

package com.blogspot.javadingsda.easytreeviewer;

import java.util.ArrayList;

public class MyTreeNode {
    
  private int depth;
  private MyTreeNode parent = null;
  private ArrayList children; 
    
  public MyTreeNode(int depth) {
    children = new ArrayList();
    this.depth = depth;
  }
    
  public MyTreeNode getParent() {
    return parent;
  }
    
  public Object[] getChildren() {
    return children.toArray();
  }
    
  public void addChild(MyTreeNode childNode) {
    childNode.setParent(this);
    this.children.add(childNode);
  }

  private void setParent(MyTreeNode parent) {
    this.parent = parent;
  }
    
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("Knoten mit Tiefe ");
    sb.append(String.valueOf(depth));
    return sb.toString();
  }

  public int getDepth() {
    return this.depth;
  }
}
Die Klasse MyTreeNode ist für die Informationen eines Knotens verantworltich. Sie enthält eine Referenz auf einen Parent und Referenzen auf alle Kinderknoten. Die Tiefe wird mit dem Attribut depth dargestellt und ist nur für unser Beispiel relevant. Die toString Methode liefert die bezeichung des Labels im Knoten. Diese Klasse ist dann optional, wenn der ITreeContentProvider die gesamte Darstellung übernimmt und nicht auf den hier vorgestellten MyTreeNode Objekten arbeitet, sondern den Baum irgendwie anders verwaltet.

Schritt 4: Erstelle die Klase TreeContentProvider.

package com.blogspot.javadingsda.easytreeviewer;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

public class TreeContentProvider implements ITreeContentProvider {

  @Override
  public void dispose() {
  }

  @Override
  public void inputChanged(Viewer viewer, Object oldInput, 
                           Object newInput) {
  }

  @Override
  public Object[] getElements(Object inputElement) {
    createChildNodes(inputElement);
    return getChildren(inputElement);
  }

  @Override
  public Object[] getChildren(Object parentElement) {
    if (parentElement instanceof MyTreeNode) {
      MyTreeNode parentNode = (MyTreeNode) parentElement;
      return parentNode.getChildren();
    }
    return null;
  }

  @Override
  public Object getParent(Object element) {
    if (element instanceof MyTreeNode) {
      MyTreeNode node = (MyTreeNode) element;
      return node.getParent();
    }
    return null;
  }

  @Override
  public boolean hasChildren(Object element) {
    if (element instanceof MyTreeNode) {
      MyTreeNode node = (MyTreeNode) element;
      if (node.getChildren().length == 0) {
        createChildNodes(node);
      }
      return true;
    }
    return false;
  }

  public void createChildNodes(Object parent) {
    if (parent instanceof MyTreeNode) {
      MyTreeNode node = (MyTreeNode)parent;
      node.addChild(new MyTreeNode(node.getDepth() + 1));
      node.addChild(new MyTreeNode(node.getDepth() + 1));
    }
  }
}

public Object[] getElements(Object inputElement)

Diese Methode wird aufgerufen, wenn der Baum das erste mal initialieriert wird, und zwar wenn die Methode setInput(Object input) des TreeViewers aufgerufen wird. In unserem Beispiel werden in dieser Methode die ersten Kinderknoten erzeugt und wiedergegeben.

public Object[] getChildren(Object parentElement)

getChildren gibt die Kinderknoten zum parentElement wieder. In unserem Beispiel hält jeder Knoten Referenzen auf die Kinderknoten. Diese können mit der getChildren Methode abgefragt werden. getChildren wird immer dann aufgerufen, wenn die Kinderknoten angezeigt werden sollen.

public Object getParent(Object element)

Wird vom TreeViewer aufgerufen, wenn dieser geschlossene Knoten programmatisch aufdecken möchte und wenn der TreeViewer den 'geöffnet' Status programmatisch setzen möchte. In unserem Beipiel kommt diese Methode nicht zum Einsatz, wird aber implementiert um der Vollständigkeit zu genügen.

public boolean hasChildren(Object element)

Bevor der TreeViewer die Kinder eines Knotens anzeigt, wird dem Benutzer visuell angezeigt, dass sich unter einem geschlossenen Knoten weitere Knoten befinden. Das Aussehen ist Betriebssystemspezifisch. In WinXP ist dies ein kleines plus Zeichen, Win7 verwendet hingegen ein kleines Dreieck links neben dem Knoten. Die Methode hasChildren liefert für diese Anzeige die Information, ob sich unter dem Knoten weitere Kinderknoten befinden. Der Übergabeparameter element ist dabei der Elternknoten. In unserem Beispiel werden zwei neue Kinderknoten für einen Elternknoten erzeugt, wenn dieser keine Kinderknoten besitzt. Somit entseht der unendliche binäre Baum.

public void createChildNodes(Object parent)

Diese Methode erzeugt zwei Kinderknoten zu einem Elternknoten.

An dieser Stelle muss noch erwähnt werden, dass das Erzeugen der Kinderknoten auch in der MyTreeNode Klasse hätte implementiert werden können. Es ist generell eine Designfrage, ob der ITreeContentProvider alle informationen von den Knoten abfragt oder diese ermittelt.

Schritt 4: Anwendung starten.
Die Anwendung kann ausgeführt und getestet werden.

Weiterlesen:

TreeViewer mit 'Drag and Drop'

TreeViewer – Ereignisse beim öffnen/schließen eines Baumkontens im TreeViewer

TreeViewer - Methoden des ITreeContentProvider

Eclipse RCP - Hintergrundfarbe und Image eines Labels im TreeViewer

Sonntag, 23. Oktober 2011

Eclipse RCP - Bilder laden und verwalten für Fortgeschrittene

Bilder werden mit Eclipse (bzw. SWT) unabhängig vom Dateityp in Image Objekte geladen. Bilder die an vielen Stellen und häufig in einer RCP Applikaiton verwendet werden, sollten mit der ImageRegistry verwaltet werden. Dieser Artikel zeigt dies in einem einfachen Beispiel wie Bilder in und aus der ImageRegistry geladen werden.
Weiterhin werden drei Möglichkeiten wie ein Pfad zu einem Bild angegeben werden kann vorgestellt.

Schritt 1: erstelle eine RCP Eclipse Anwendung die auf dem Template "RCP Application with a view" basiert

Schritt 2: kopiere das Bild "alt_window_32.gif" in das Package in dem sich die View Klasse befindet. Das Projektverzeichnis sollte wie in Abbildung 1 dargestellt aussehen.

Abbildung 1
Schritt 3: in der Klasse View müssen alle inneren Klassen und Attribute gelöscht werden. Der Inhalt der Methoden createPartControl und setFocus sollte ebenfalls gelöscht werden. Der Inhalt der Methode createPartControl wird mit dem Inhalt wie im Programmauszug 1 ersetzt.


import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
  public static final String ID = 
               "com.blogspot.javadingsda.testimageregistry.view";

  public void createPartControl(Composite parent) {
    GridLayout layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    parent.setLayout(layout);

    ImageRegistry reg = Activator.getDefault().getImageRegistry();

    Label label = new Label(parent, SWT.NONE);
    GridData gridData = new GridData();
    label.setData(gridData);
    label.setImage(reg.get("testpic"));

    label = new Label(parent, SWT.NONE);
    gridData = new GridData();
    label.setData(gridData);
    label.setImage(reg.get("testpic2"));

    label = new Label(parent, SWT.NONE);
    gridData = new GridData();
    label.setData(gridData);
    label.setImage(reg.get("testpic3"));
  }

  public void setFocus() {}
}
Programmauszug 1

Schritt 4: das Laden der Bilder in die ImagerRegistry kann an beliebiger Stelle erfolgen. Es sollte nur vor der ersten Verwendung erfolgen. Wir entscheiden und dies in der Perspective Klasse zu tun. Programmauszug 2 zeigt die modifizierte Klasse.
Bei Lösung 1 und Lösung 2 wird das Bild aus dem icons Verzeichnis geladen. Lösung 3 läd das Bild aus dem Package in dem sich die View.class befindet.

import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
import org.osgi.framework.Bundle;

public class Perspective implements IPerspectiveFactory {

  public void createInitialLayout(IPageLayout layout) {
    layout.setEditorAreaVisible(false);
    layout.setFixed(true);

    ImageRegistry regystry = 
                     Activator.getDefault().getImageRegistry();
    String pathStr = "icons/alt_window_32.gif";
    Path path = new Path(pathStr);

    // Lösung 1
    Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID);
    URL url = FileLocator.find(bundle, path, null);
    ImageDescriptor imageDescriptor = 
                    ImageDescriptor.createFromURL(url);
    regystry.put("testpic", imageDescriptor);
    // Lösung 2
    ImageDescriptor imageDescriptor2 = 
                    Activator.getImageDescriptor(pathStr);
    regystry.put("testpic2", imageDescriptor2);
    // Lösung 3
    ImageDescriptor imageDescriptor3 = 
       ImageDescriptor.createFromFile(View.class, "alt_window_32.gif");
    regystry.put("testpic3", imageDescriptor3);
  }
}
Programmauszug 2


Die gezeigten Beispiele bauen auf folgenden Quellen:


//http://www.javalobby.org/forums/thread.jspa?threadID=16557
//http://www.eclipse.org/articles/Article-RCP-2/tutorial2.html
//http://www.eclipse.org/articles/Article-Using%20Images%20In%20Eclipse/Using%20Images%20In%20Eclipse.html
//http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html

Freitag, 21. Oktober 2011

Eclipse RCP / SWT Tabulator Reihenfolge bestimmen

Um die Tabulator Reihenfolge zu bestimmen müssen die Referenzen der Widgets in einem Array in der gewünschten Reihenfolge an das Composite übergeben werden, dass die Widgets enthält.


@Override
public void createPartControl(Composite parent) { 
    ... 
    Button b1 = new Button(parent, SWT.NONE); 
    ... 
    Button b2 = new Button(parent, SWT.NONE); 
    .... 
    Button b3 = new Button(parent, SWT.NONE); 
    ...
    Control[] controls = new Control[] { b2, b1, b3 }; 
    parent.setTabList(controls); 
}

Montag, 17. Oktober 2011

Blogs und Websites meiner Freunde und Bekannten

Da mich einige Freunde gebeten haben einen Link zu Ihrer Seite in meinem Java Blog zu platzieren, möchte ich in diesem Post einige davon mit einen kurzen Kommentar auflisten.

Simvelop GmbH
Webpage von Miroslav Simudvarac. Er ist passionierter Sowtwareentwickler und betreibt seit einigen Jahren recht erfolgreich ein IT Unternehmen.Seine Produkte und Dienstleistungen könnt ihr auf seiner Seite finden.


www.stefan-pochmann.info 
Wer einen echten Lebenskünstler sehen möchte der sollte auf jeden Fall die Internetseite von Stefan Pochmann sehen. Stefan ist ein begnateter Rubik Fan und programmiert auch gerne mal die Nacht durch.

strangeoptics.blogspot.com
Die Seite von meinem Arbeitskollegen Alex. Dort sind einige Programmiertips zu finden zu Java und Android Programmierung sowie Tipps wie man Pilze such und Kocht (oder so ähnlich)!



Fortsetzung folgt...

Mittwoch, 12. Oktober 2011

Eclipse RCP - IFolder nach dem Beenden der letzten View erhalten

Problem: nachdem die letzte View geschlossen wird, verschwindet auch der IFolder. Werden neue Views wieder geöffnet, dann erscheinen diese nicht immer in einem Teil des Fensters. Die Anwendung sieht dann recht unkonsistent aus, wie in Abbildung 1 dargestellt.


Abbildung 1

Lösung: Im WorkbenchWindowAdvisor (bzw. in der Klasse die von diesem erbt) muss die Methode isDurableFolder überschriben werden:


@Override
public boolean isDurableFolder(String perspectiveId, String folderId) { 

  if (folderId.equals("folderName")) {
    if ("perspective.id".equals(perspectiveId)) {
      return true;
    }
  }
  return super.isDurableFolder(perspectiveId, folderId); 
}

Der folderName ist der Name des IFolder der in der Persepctive Klasse angelegt wurde. perspective.id ist die im plugin.xml eingetragene ID der Perspective.

Das Ergebnis ist in Abbildung 2 dargestellt:

Abbildung 2


Hier ein Auszug aus der Perspective Klasse:


public class Perspective implements IPerspectiveFactory {
    public static final String ID = "perspective.id";

    public void createInitialLayout(IPageLayout layout) {
      String editorArea = layout.getEditorArea();
      layout.setEditorAreaVisible(false);
      layout.addStandaloneView(NavigationView.ID, false, 
                     IPageLayout.LEFT, 0.25f, editorArea);
      IFolderLayout folder = layout.createFolder("inputFolder", 
                     IPageLayout.TOP, 0.5f, editorArea);
      layout.getViewLayout(NavigationView.ID).setCloseable(false);
    }

}

Anzumerken sei, dass derartige Verweneung der isDurableFolder Methode auf den Spezialfall einer Applikation mit einen Navigationsbaum links und dem Inhalt rechts passt. Sollten komplexere GUIs gefordert sein, muss die Methode entsprechned modifiziert werden.

Dieser Artikel basiert auf folgendem Posting bei stackoverflow.com.

Sonntag, 9. Oktober 2011

Eclipse RCP - Extensions Editor zeigt im "Generic" im im "New" Menü

Problem: im Extensions Editor der plugin.xml Datei wird beim Versuch ein neues Command oder eine neue View anzulegen im Menü New nur das Untermenü Generic angezeigt. Das Problem tritt auch manchmal auf, nachdem eine Target Platform erstellt (eingestellt/geändert) worden ist. Abbildung1 zeigt den Extension Editor mit dem oben beschriebenen Problem. Das erstellte Plugin ist das RCP Mail Template.

Auch beim Klicken auf "Show Description"  oder "Open Schema" erhält man die Meldung "Description for extension point …… cannot be found" bzw. “Extension point schema for extension point ….. cannot be found.”


Abbildung1: nur Generic sichtbar


Ursache: die Scoucen (Quellcode) der Plugins im Bundle sind in der Target Platform nicht vorhanden.

Nachdem das Plugin erstellt worden ist, ist eine Targetplatform aus dem Template "Base RCP (Binary Only)" erstellt worden. Anschließend wurde diese Target Platform aktiviert.

Anstatt des "Base RCP (Binary Only)" Templates kann das Template "Base RCP (with Source)"verwendet werden. Wird die Targetplatform mit den Sourcen verwendet taucht das oben genannte Problem nicht mehr auf.

Diesen Artikel habe ich erstellt, nachdem ich selbst über das Problem gestolpert bin und eine sehr gute Beschreibung in englischer Sprache gefunden habe. Ein Blick in den orginalen Artikel lohnt sich.

Sonntag, 2. Oktober 2011

Eclipse RCP - Anwendung aus dem "RCP Mail Template" erzeugen

Dieser Artikel beschreibt kurz, wie eine RCP Anwendung aus dem Mail Template erzeugt werden kann. Diese Anwendung, bzw. der Weg diese zu erstellen ist die Basis für einige der hier beschriebenen Beispiele.
  
Schritt 1: ein neues Plug-In Projekt mit dem Namen com.blogspot.javadingsda.testprojekt anlegen. Mit der Schaltfläche "Next>" weiter.


Abbildung 1: neues Projekt anlegen

Schritt 2: Eingaben entsprechend der Abbildung 2 vervollständigen und mit Schaltfläche "Next>" weiter.

Abbildung 2:Plug-In Project anlegen


Schritt 3:  "RCP Mail Template" auswählen und mit der Schaltfläche "Finish" den Wizard beenden.

Abbildung 3: "RCP Mail Template"auswählen



Schritt 4: Anwendung als "Eclipse Application" ausführen.