# Problem beim neuanlegen von Composites



## dzim (23. Mrz 2010)

Hi zusammen,

ich habe bereits vor einiger Zeit eine Art Wizard konstruiert (ich brauchte mal was, was in einem Editor ausgeführt werden kann und nicht als Wizard-Dialog - über Sinn und Unsinn lässt sich sicher streiten, aber er funktioniert augenscheinlich relativ gut).
Seit einigen Tagen versuche ich ihn noch etwas zu erweitern, was leider nur von mäßigen Erfolg gekrönt ist:
Jede Page und der Wizard selbst können einen Name haben (wenn man ihn nicht setzt, wird je ein Default-Wert verwendet).
Ich möchte nun - vergleichbar mit dem Diagramm-Wizard von OpenOffice (der einzige, der mir gerade einfällt) - auf der Seite einen Überblock über den Inhalt (also die Seiten) des Wizards geben und die aktive Seite hervorheben, bzw. auch die, die noch nicht erreichbar sind markieren (rote Schrift oder so).

Ich habe das Ganze über eine SashForm gemacht und für eine Einzelne Seite, wird der Name des Wizards und der Seite bereits ordentlich angezeigt. Aber:
Ich möchte das Composite (=Client-Area in einer Section, welche in einem ScrolledForm steckt) bei jedem hinzufügen einer Seite (was von der API her halt auch "während des Betriebs" möglich ist), bei jedem Wechsel der Seite, oder jeder Statusänderung einer Seite (ob man zu nächsten weiter gehen kann oder nicht), neu darstellen.

Dazu mache ich folgendes:

```
private void createOverviewContent() {

		// create a new content section composite
		overviewContentComposite = new Composite(overviewContentSection,
				SWT.NONE);

		// adapt composite to forms
		formToolkit.adapt(overviewContentComposite);
		formToolkit.paintBordersFor(overviewContentComposite);

		// create the client-area of the section
		overviewContentSection.setClient(overviewContentComposite);
		overviewContentComposite.setLayout(new FormLayout());

		// the last label, used to attach ne next one
		Label lastLabel = null;
		for (int i = 0; i < pages.size(); i++) {

			// used to mark the current page
			boolean currentPage = false;
			if (((StackLayout) contentComposite.getLayout()).topControl == pages
					.get(i).getTopComposite()) {
				currentPage = true;
			}

			// create the text for the label...
			String text = (i + 1)
					+ ") "
					+ (pages.get(i).pageName != null ? pages.get(i).pageName
							: "page " + (i + 1));
			// ... and create it
			Label label = formToolkit.createLabel(overviewContentComposite,
					text, SWT.WRAP);

			// attachment via FormLayout --> don't know if this is a good approach at all
			FormData fd_label = new FormData();
			if (i == 0) {
				fd_label.top = new FormAttachment(0, 5);
			} else {
				if (lastLabel != null) {
					fd_label.top = new FormAttachment(lastLabel, 5, SWT.BOTTOM);
				}
			}
			fd_label.left = new FormAttachment(0, 5);
			fd_label.right = new FormAttachment(100, -5);
			label.setLayoutData(fd_label);

			// set the coloring
			if (currentPage) {
				if (pages.get(i).canProceed) {
					label.setForeground(SWTResourceManager.getColor(0, 0, 0));
				} else {
					label.setForeground(SWTResourceManager.getColor(255, 0, 0));
				}
				label.setBackground(SWTResourceManager.getColor(0, 204, 0));
			} else {
				if (pages.get(i).canProceed) {
					label.setForeground(SWTResourceManager.getColor(0, 204, 0));
				} else {
					label.setForeground(SWTResourceManager.getColor(255, 0, 0));
				}
			}

			// remember the last label (for the form-data)
			lastLabel = label;
		}

		// force an update of the composite and it's parent
		// i guess there is something wrong here...
		overviewContentComposite.update();
		overviewContentComposite.getParent().layout(
				new Control[] { overviewContentComposite });
	}
```

Ich habe es so weit bereits durchgetestet: die Methode wird an allen fraglichen Stellen aufgerufen (in diversen Listenern etc.).
Ein Effekt ist aber leider bislang ausgeblieben.

Wenn jemand sieht, wo ich da vielleicht auf der Stelle trete...

Vielen Dank und Gruß
Daniel


----------



## Wildcard (23. Mrz 2010)

Dein Problem ist das diese 'overview' nicht richtig aktualisiert wird?
Sections sind nicht dafür gedacht das du ihnen n Controls hinzufügst (du erstellst ja jedesmal ein neues Composite).
Mach doch ein Composite in die Section, setze es als Client. Dieses Composite nutzt du als Parent für deinen Variablen Inhalt.
1. Änderung passiert
2. Du disposed den aktuellen Inhalt (wichtig)
3. Du erzeugst den neuen Inhalt auf dem Composite
4. Du rufst Layout auf der Section auf


----------



## Wildcard (23. Mrz 2010)

Übrigens, hast du dir mal MasterDetailsBlock angesehen? Das entspricht wohl in etwa dem Paradigma das du dir vorstellst und nimmt Arbeit ab.


----------



## dzim (24. Mrz 2010)

Zu deiner ersten Antwort: ja, diese overview wird nicht richtig aktualisiert.
Mit "overviewContentSection.setClient(overviewContentComposite);" (Zeile 12) dachte ich, dass ich es bereits als Inhalt setze - die Labels, die die Darstellung der aktuellen Seite etc übernehmen sollen, werden auf diesem Composite dargestellt - wenigstens in der Theorie.
Was ich aber tatsächlich nicht gemacht habe, ist das disposen der bereits vorhandenen Elemente... Vielleicht ist dass das Problem und ich geh es schon wieder viel zu kompliziert an!

Ja, ich hab schon mal mit dem Master-Details-Block herumgespielt (auch wenn ich, ehrlich gesagt, nie etwas im Endeffekt damit konstruiert hab, was auch funktioniert hätte ;-) )
Ich weiß aber nicht, ob der MDB hier genau das richtige ist, da ich in meinem Wizard - vergleichbar zu der aufklappenden Hilfe in einigen Dialogen/echten Wizards - dort (wenn man so will im "Detail") zwar immer Forms verwende, aber im eigentlichen "Master", was nix weiter als ein einfaches Composite mit StackLayout, auch Nicht-Forms verwendet werden können.
Ich steck im MDB nicht so tief drin, daher weiß ich nicht, ob ihm das egal ist oder nicht!


----------



## dzim (30. Mrz 2010)

WTF!!!
Wildcard! Ich könnt mir selbst in den Arsch beißen! Du hattest recht!
Ich frag mich, warum ich da nicht mal selbst drauf komme!

Disposen, Content neu anlegen, layout forcieren und fertig!

Danke, danke, danke!


----------

