amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Suche [ - Suche - Neue Beiträge - Registrieren - Login - ]

Erste 2 3 4 5 6 -7- 8 9 10 11 12 >> Letzte Ergebnisse der Suche: 1229 Treffer (30 pro Seite)
Der_Wanderer   Nutzer

18.07.2011, 11:19 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zitat:
Und ein Popup menu kann noch nicht objekte enthalten, sondern ist eine eiheit.
Wenn du es richtig machst, dann kann ein PopUp Object wiederum alles enthalten. Das ist dann sehr mächtig.
Ich überlege z.B. gerade, ob ich den Tab eines Tabview nicht auch als Gruppe organisiere, sodass man dort reintun kann was man will, z.B. mehrere Grafiken oder einen Close Button etc.

Zitat:
Mein Interesse gilt da noch der Strategie bei Mausklicks in views in views. man muß da ja nicht nur fragen, ob die maus über einer view ist, sondern auch eine zweite, die sich mit der ersten überschneidet, muss die mögliche fläche mit eingrenzen. naja, das schaffe ich schon noch.
Der Test, über welchem Objekt ich mich befinde geht auch hierarchisch. So kann z.b. ein ScrollView den Mausklick Offset verschieben oder die Weiterleitung stoppen, falls nötig.

Zitat:
Aber wie ist es nun mit dem Notify? Das interessiert mich am meisten.
Das ist einfach. Ein Objekt kann verschiedene Notify Values haben.
z.B. "OnClick". Ein Button kann dann, falls ein Notify Wert gesetzt ist, eine Notify Message generieren wenn er merkt dass er geclickt wird.
Je nach Objekt kann es durchaus eine ganze Reihe von solchen Gelegenheiten geben, wo man ein Notify los werden will.
Z.b. OnClick, OnTouch, OnRelease, OnChange, OnFocus, OnMouseOver, OnTick etc...
Wenb der User allerdings keine Notify Werte setzt, dann bekommt er auch keine. So muss sich der User nicht um jeden Dreck kümmern, sondern nur darum was ihn interessiert. Z.b. setzt er bei einem Button
OnClick = "QuitApplication".
Er kann aber z.B. auch bei einem Menu Item den gleichen Notify Wert setzen, und auf den CloseButton eines Fenster auch.
Dann muss er nur einmal auf "QuitApplication" lauschen, und sich nicht mit Details rumschlagen wer nun der Auslöser war. Kann auch eine AREXX Message gewesen sein oder ein CTRL+C.
Wichtig ist halt, dass man nur einmal das Programm Ende empfängt und implementiert. Später kann man diese Notify Value überall dort eintragen, wo man beim GUI Desgin der Meinung ist dass diese Notify Ausgelöst werden soll. Das ist der grundlegende Unterschied zwischen Notify und Event.

Zitat:
Und zum "überladen" von Funktionen: meine subclass könnte auch die message immer zuerst bekommen und wenn sie will dann noch hinterher oder vorher den dispatcher der elternklasse aufrufen. so spart man
sich die evtl vielen funktionspointer. so kann man Zb auch einen Slider um pfeilebuttons erweitern, oder? naja, ist nicht ganz das selbe wie das was du da hast... bei dir kann man ja sogar pro objekt andere funktionen haben..

Weis nicht genau wie du das meinst, aber die paar Pointer pro Object kann man verkraften, oder nicht? Der Vorteil ist, dass jedes Objekt individuell einen Satz von Funktionen haben kann, der auch der App Programmierer austauschen kann, wenn er was ganz spezielles benötigt was das GUI Toolkit nicht vorgesehen hat.

Pfeil Buttons bei Slidern mache ich ganz anders.
Das sind einfach Kinder des Sliders und stink normale Buttons.
Beim Initialisieren des Sliders werden sie allerdings mit dem Slider verknüpft, mit einem sog. "Binding". Das ist ein gerichteter Ring von Objekten. Wenn sich eines ändert, ändern sich die anderen dann mit.
Dazu brauchst du ein zusätzliches Feld in deinem Objekt was einen Pointer auf das nächste Objekt in der Bind Group hat.

Dazu aber vielleicht später mehr...


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

17.07.2011, 22:02 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zum RastPort:

Die Aussage war, du solltest von dem RastPort Pointer keine Kopie erstellen. Du solltest grundsätzlich vermeiden, Kopien von Pointern zu erstellen, denn ein Pointer kann an anderer Stelle ungültig gemacht werden, und somit hast du einen Seiten Effekt.
Seiten Effekt == böse böse böse und führt zu anfälligem und schwer wartbarem Code.

Statt dessen gehst du in deinem Baum nach "oben", solange bis ein Objekt kommt was einen RastPort besitzt, in den du malen sollst. z.B. ein Fenster oder auch ein aufgeklapptes Pop Up Menu. Kann natürlich auch NULL sein, wenn das Fenster zu ist. Dann machst du in deinem Draw einfach nichts und springst zurück.

Der Mehraufwand, den Pointer zu holen ist überschaubar.

Der Mehraufwand, Kopien von Pointern zu synchronisieren, scheint am Anfang geringer, wächst aber bei zunehmender Komplexität ins Uferlose und so schaufelst du deinem GUI Toolkit sein Grab...

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 22:04 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 22:05 Uhr geändert. ]
 
Der_Wanderer   Nutzer

17.07.2011, 21:50 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zum Überladen von Funktionen, (oder im OOP Sprachgebraucht Vererbung und Subclassen von Methoden):

Jedes Object hat Function-Pointer auf seine Version z.b. von Layout, Dispatch oder Draw.

Es kann z.B. eine allgemeine Function geben für Layout, wo einfach nur die Boundaries gesetzt werden, was mehr oder weniger für jedes Object zutrifft.

Wenn jetzt aber ein Object "FooBar" was Spezielleres benötigt, kann man die Funktion "überladen". Bzw, im OOP Sprachgebrauch würde das bedeuten, das speziellere Object "FooBar" ist nun eine Subklasse vom allgemeinen Object "Widget" und kann diverse Funktion "überladen", also ersetzen. Konkret wird der Function-Pointer von z.B. "WidgetLayout(bounds)" auf "FooBarLayout(bounds)" umgesetzt. FooBarLayout() sollte natürlich auch die Boundaries setzen (z.b. durch Aufruf von WidgetLayout()), könnte aber noch andere organisatorischen Dinge tun wie z.B. Offsets von Text etc. berechnen, damit das später beim Draw() schneller geht und vor allem Kinder-Objekte platzieren und deren Layout Funktion aufrufen.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 21:54 Uhr geändert. ]
 
Der_Wanderer   Nutzer

17.07.2011, 21:30 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Normalerweise ist das so:

Du hast eine Routine, die die Events beim Betriebssystem abholt.
Die heisst bei mir CollectAmigaEvents().
Da sind dann IDCMP, App, AREXX, ScreenNotify usw. drin, alles was ein Programm so empfangen kann/möchte.

Die Funktion erstellt dann Events im Format des GUI Toolkits. Das ist wichtig, wenn man es portabel halten will, da man dann lediglich CollectAmigaEvents() gegen CollectSDLEvents(), CollectWin32Events() etc. austauschen muss, und alles danach bleibt gleich.

Aber auch wenn man nicht vor hat es zu portieren, ist das eine gute Idee die Events in eine sog. kanonische Form zu bringen, damit sich die Widgets nicht mit Implementationsdetails von AmigaOS herumschlagen müssen, was mitunter etwas kompliziert werden kann. So hat man den ganzen "Dreck" in eine Funktion zusammengeschnürt, und fasst das dann besser nie wieder an...

Also nachdem man nun ein "MyGUIToolkit"-Event hat, also ein Struct was so aussieht wie du es verarbeiten willst, dann muss man sich fragen, wohin damit. Da muss man sich nun eine clevere Rangfolge überlegen, um später möglichst flexibel zu sein.

Was jetzt kommt nennt man "dispatchen". Es ist immer gut, sich die gebräuchliche Terminologie anzueignen, dann versteht jeder "sachkundige" gleich was du vor hast.

Beim Erstellen eines Events in dem Format deines GUI Toolkits wurde in die Struct das Urheber Object eingetragen, z.B. das Window, wo ein Mausklick entstanden ist, oder der AREXX Port der eine Message empfangen hat. (wie gesagt, das Object, nicht ein Pointer auf Window oder AREXX Port, das wäre ja wieder OS spezifisch und ist js auch bereits abgefrühstückt in CollectAmigaEvents).

Der Urheber, ein GUI Toolkit Object, bekommt nun dieses Event in seiner "dispatch" Funktion aufgerufen.
Der kann dann frei entscheiden, was er damit tut.
Der häufigste Fall dürfte ein Window sein. Deine Windows haben dann, wie alle Objekte, eine Dispatch Funktion. Die kann sich dann, in Abhängigkeit was für ein Event es ist, überlegen was passiert.

Z.B. ist es ein "Close" Event, dann kann sich das Window schließen.

Ist es ein Mausklick, dann fängt die Dispatch Funktion des Windows an zu prüfen, wer damit was anfangen kann.
Als erstes sollte das Object gefragt werden, das den Focus hat, indem das Event mit der Dispatch Funktion des Focus-Pbjects aufgerufen wird. Das Object könnte dann theoretisch wiederum weiterdelegieren oder etwas mit dem Event machen. Macht es nichts mit dem Event, gibt die Dispatch Funktion FALSE zurück, wenn sie was damit gemacht hat, dann TRUE.

So weis die Übergeordnete Dispatch Funktion, ob das Event "konsumiert" wurde oder noch nicht.
Will also nun z.B. das Objekt mit dem Focus das Event nicht, gibt dessen Dispatch Funktion FALSE zurück. (z.B. bei einem Mausklick außerhalb der Boundaries).
Dann ist wieder die Dispatch Funktion des Fensters an der Reihe. Es delegiert nun das Event weiter an das Object, worüber der Mauspfeil steht. Meistens konsumiert dann dieses Objekt das Event. Wenn nicht, könnten wir noch andere Sachen anstellen, aber bei NTUI ist dann bereits Schluß und das Fenster selbst gibt FALSE zurück.

Dann sind wir wieder auf Engine Dispatch Ebene, was mit einem Mausklick nix anfangen kann, und das Event wird endgültig entsorgt ohne Effekt.

Die Dispatch Strategie kann natürlich verschieden aussehen. So wie ich es bei NTUI mache denke ich aber ist es gut und flexibel. So kann z.b. ein Objekt den Mauspfeil ändern beim drüber fahren, z.B. ein Listview um die Colums zu verschieben, aber trotzdem könnte das Objekt mit dem Focus auch auf Mausbewegungen reagieren und ein Ändern des Mauspfeils unterbinden, falls es das Event konsumiert.

Beispiel:

Du hast eine TextBox, die normalerweise den üblichen Text-Edit Mauspfeil setzt wenn man darüberfährt (das macht die TextBox in ihrer Dispatch Funktion, sobald ein MouseMove kommt der innerhalb der Boundaries liegt).
Jetzt hat aber z.B. ein Cycle Button den Focus. Die TextBox soll aber natürlich trotzdem reagieren können.
Das funktioniert so, dass der Cycle Button bei MouseMove Events "FALSE" zurückgibt, es interessiert ihn also nicht, somit bekommt danach das Mouse-Over Objekt das Event angeboten, hier die TextBox.

ABER: wenn ich jetzt den CycleButton aufklappe und gedrückt halte, und die Maus aus der Auswahlbox rausbewege, möchte ich NICHT, dass die TextBox reagiert. (oder die Auswahlbox könnte ja über die TextBox ragen). Während der Cycle Button also gedrückt ist, kann er die MouseMove Events konsumieren, gibt im Dispatch also TRUE zurück. Somit kommt das Event nicht mehr bei der TextBox an, und sie kann nicht den Text-Edit Mauspfeil setzen.

Pew! Macht das Sinn für dich soweit?


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 21:43 Uhr geändert. ]
 
Der_Wanderer   Nutzer

17.07.2011, 12:04 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

1. Jedes Objekt hat auch einen Pointer auf das Elternobjekt.
Wenn du einen RastPort brauchst, dann läufst du so lange nach oben bis eines der Objekte sage "Hey, ich wäre derjenige der den RastPort zur Verfügung stellt!".
Das muss nicht immer ein klassisches Fenster sein, z.B. bei einem Pop Up Menu wäre es das Subwindow des Menu Titles, oder beim aufgeklappten Cycle wäre es das Subwindow des Cycle Buttons.

Das macht man auch Rekursiv, z.b. mit einer Methode wie "GetRastPort(object)". Wenn das Objekt kein eigenen RastPort hat, dann rüft es einfach "GetRastPort(object->parent)", und irgendjemand in der Reihe wird dann schon was tun. Kann natürlich auch NULL zurückkommen, wenn z.b. das Fenster zu ist.

2. Das mit dem Get/SetAttr macht man mit "Überladen".

Also stell dir vor, du hast ein Integer Wert, den man bei jedem Gadget wieder findet. Dann schreibst du eine allgemeine Funktion (also für ein Object, nicht ein spezielles Widget), z.b.

code:
SetInteger(object this, int value) {
  this.value = value;
}


Jetz gibt es aber ein paar Ausnahmen, z.b. ein Object anmens "Foobar" wo z.b das Value nicht negativ sein darf und dann auf 0 geklippt werden soll, aber eben nicht bei allen.
Das heißt jetzt nicht, dass du jedem Object nun eine eigene Implementierung verpassen musst, nur dem einen speziellen.
Wenn du keine Sprache nutzt, die OOP macht, dann machst du das so mit hilfe von Funktionpointer, die jedes Object speichert. Wenn der Funktionpointer NULL ist, wird die Eltern-Implementierung genutzt.


code:
/* Spezielle Funktion für Foobar */
void Foobar::SetInteger(object this, int value) {
  Foobar fb = (Foobar)this; /* der Cast ist hier unnötig, aber i.A. notwendig */ 
  if (value<0) value=0;
  fb.value = value;
}

/* Allgemeine Funktion auf "Object" Ebene */
void Object::SetInteger(object this, int value) {
  if (this.SetInteger!=NULL) { /* wir haben eine spezielle Funktion */
    this.SetInteger(this,value);
  } else { /* wir nutzen die allgeimeine Funktion */
    this.value = value;
  }
}


Die Funktionpointer werden bei der Initialisierung gesetzt.
Theoretisch könnte jetzt auch der App Programmierer hergehen, und eine dieser Funktionen austauschen, für maximale Flexibilität.

Das ganze nennt man "eine Funktion überladen".
Das kann man auch durch mehrere Hierarchie Ebenen hindurchziehen.
Auch ist es möglich, z.b. bei einer Draw Funktion, die "alte" weiterhin zu benutzen und nur ein kleine Ändrungen hineinzutun,
z.B. Markierungen in einem Slider.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 12:10 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 12:10 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 17.07.2011 um 12:13 Uhr geändert. ]
 
Der_Wanderer   Nutzer

16.07.2011, 11:20 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Ja, bei mir wäre eine Größenänderung auch das gleiche wie ein Layout.
Schliesslich muss man, je nach Widget, ein eMenge anpassen je nach Größe.

Wegen dem RastPort beim Layout... den hole ich mir immer durch hochlaufen zum Fenster.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

15.07.2011, 12:55 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Achja, und wichtig ist es gedanklich zwischen verschiedenen Formen von "Visible" zu unterscheiden.

Das was du "Visible" nennst, nenne ich in NTUI "OnScreen" und bedeutet, dass das Widget tatsächlich auf dem Bildschirm sichtbar ist, also z.b. auf Refresh Anfragen reagiert oder verwirft. Dieses Flag darf ausschließlich die Layout Methode setzen oder löschen.

Im Gegensatz dazu gibt es gibt es ein Visibility Feld in jedem Objekt, das anzeigt wie unser Objekt layouted werden soll. Diese Feld kann man mit Get/SetAttr ändern als User.

Visiblity kann "Visible", "Hidden" oder "Gone" sein.

"Visible" ist klar, d.h. das Widget wird ganz normal layouted und ist sichtbar, bekommt als ggf. das OnScreen Flag gesetzt.

"Hidden" heißt, dass zwar der Platz im Layout berücksichtigt wird, es wird also layouted, aber es wird nicht gezeichnet (wird also auch niemals "OnScreen").

"Gone" bedeutet, das Objekt existiert war (und kann z.B. mit Get/SetAttr angesprochen werden), wird aber vom Layout komplett ignoriert als wäre es nicht da.




--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

15.07.2011, 12:45 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

RastPort Pointer würde ich auf keinen Fall permanent in einem Widget ablegen.

Ein sehr wichtiger genereller Tip:

code:
/////////////////////////////////////////////////////////
//                                                     //
//  Niemals EINE Information an ZWEI Orten speichern!  //
//                                                     //
/////////////////////////////////////////////////////////

(=>Vermeidung von Redundanz)

Denn das führt schnell zu enormen sog. Bookkeeping Aufwand und ist eine super Quelle für Bugs.
Bookkeeping bedeutet, du musst Code schreiben der eigentlich nix macht ausser zu gucken, dass auch ja immer überall der richtige RastPort eingetragen ist, also purer Overhead Code.

Deshalb: Speichere den RastPort nur an einem Ort. Wenn es ein Window ist, dann steht er in der Window Structur bereits drin, als mache KEINE Kopie davon. Wenn er gebraucht wird, dann sollte er sich vom Window besorgt werden. Ist ja kein Problem den bei Draw, MinSize oder Layout als Parameter zu übergeben.

Das gleiche gilt für den AmigaOS-Window Pointer selbst. Bei mir steht er nur an einer Stelle, nämlich im Window Objekt, das den AmigaOS Window Pointer hält, falls das Window offen ist. Kann ja auch geschlossen sein, und das Window Objekt existiert trotzdem noch, z.b. beim Iconifizieren.

Generell würde ich von der Denkweise abrücken, dass nur existiert was man auch sieht (wie es AmigaOS macht).
In NTUI baue ich die GUI auf, und die Applikation kann mit ihr ganz normal arbeiten, egal in welchem Zustand sie ist.
D.h. in Iconifiziertem zustand kann ich genauso Werte setzen oder auslesen, als wenn das Fenster offen ist oder auch geschlossen,
ob das Widget nun auf einem nicht sichtbaren Tab ist oder nicht.

D.h. die App selbst muss keine Kenntnis über das Aussehen der GUI haben.
--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 15.07.2011 um 12:58 Uhr geändert. ]
 
Der_Wanderer   Nutzer

14.07.2011, 22:17 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Höre auf Holger.

Die Kinder Widgets der Tabs sollten alle immer existieren. Aus der "richtigen" Liste der Kinder herauszunehmen oder gar zu deiniten ist keine gute Idee. Evtl. kannst du das mit einem "Hidden" Flag lösen, das Rekursiv für alle Kinder gesetzt wird.

Z.b. möchtest du ein Widget aktualisieren können, obwohl es gerade nicht sichtbar ist. Wenn man dann den Tab umschaltet, sollte es dann den aktuellen Stand zeigen.

Bei NTUI kannst du sogar Widgets aktualisieren deren Fenster zu ist.

Als App Programmierer sollte dich nicht interessieren (müssen), ob, wo und in welchem Fenster ein bestimmtes Widget sichtbar ist. Dir kommt es ja nur auf die Logik an, nicht auf die Darstellung.
Dadurch hat das Toolkit dann mehr flexibilität, z.b. an/abocken von Toolbars ist möglich, oder pop-up Menues die wiederum beliebige Widgets enthalten.



--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

13.07.2011, 21:08 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Den Foreground habe ich eigentlich noch nie benutzt. Wie auch immer, hast du das mit dem Draw "von oben" jetzt verstanden?

Genau den gleichen Mechanismus benutzen bei mir eigentlich alle Widget Methoden, die da wären:

CalculateMinSize();
Berechnet die Mindestgröße des Widgets.

code:
METHOD Widget::CalculateMinSize()
{
  FOR EACH this.child {
    this.minsize += this.child.CalculateMinSize();
  }

  this.minsize += ownminsize

  RETURN this.minsize
}



Layout();
Setzt die tatsächlichen Boundaries der Widgets.

code:
METHOD Widget::Layout(boundary)
{ 
  this.boundary = boundary

  FOR EACH this.child {
    this.child.Layout(PART_OF(boundary));
  }
}



Draw();
Zeichnet die Widgets.

s.o.

DispatchEvent();
Sendet Events (Mouseklick, Keyboard etc.) an die Widgets.
code:
METHOD Widget::DispatchEvent(event)
{ 
  FOR EACH this.child {
    IF HASFOCUS(this.child) done = this.child.DispatchEvent(event);
  }

  IF NOT INTERESTED (event) THEN RETURN FALSE
  IF done=TRUE THEN RETURN TRUE

  DO SOMETHING WITH EVENT // z.b. Status updaten oder Notify generieren

  RETURN TRUE
}


Init()
Initialisiert ein Widget.

code:
METHOD Widget::Init() 
{
  INITIALIZE this

  // wenn wir Kidner brauchen, z.b. Scroller oder Knöpfe:
  this.child = CREATE NEW WIDGET

}



Deinit()
Gibt die Resourcen eines Widgets frei.
code:
METHOD Widget::Deinit()


  FOR EACH this.child {
    this.child.Deinit();
  }

  FREE this  
}


SetAttr()
Setzt ein Attribut eines Widgets.

SetAttr()
Liesst ein Attribut eines Widgets.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 13.07.2011 um 21:18 Uhr geändert. ]
 
Der_Wanderer   Nutzer

13.07.2011, 17:28 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Im Prinzip sieht die Zeichenfunktion für jedes Widget so aus:

(Pseudo Code)

code:
METHOD Widget::Draw(Rect clip) {

  IF (this OUTSIDE clip) RETURN // wir sind ausserhalb des clips => und tschüss!

  myclip = clip AND this.boundary // verenge den Clip auf unsere Boundaries (Schnittmenge)

  oldclip = INSTALLCLIPREGION(myclip) // setze den Clip für die Zeichenfunktionen

  DRAW_BACKGROUND_FOR_THIS_WIDGET // male unser Widget, z.b. Group Frame oder einen Button

  FOR EACH this.child { // falls wir Kinder haben, dann male diese auch, mit dem verengten Clip
    this.child.Draw(myclip)
  }

  DRAW_FORGROUND_FOR_THIS_WIDGET // falls vorhanden, z.b. ein Glossy Effekt oder überlappende Elemente wie Slider Marker


  myclip = INSTALLCLIPREGION(oldclip) // alten Clip wieder herstellen
  FREECLIPREGION(myclip) // unseren frei geben

  RETURN // und wech!
}


Wenn man z.b. einen Button neu zeichnen will, dann ruft man

root.Draw(Button.boundary)

(wobei "root" normalerweise ein Fenster ist)
auf, und alles sollte genau so laufen wie es soll...

Für einen completten Refreh des Fensters würde man

root.Draw(root.boundary)

aufrufen, oder z.B. NULL als Boundary, um anzuzeigen dass man initial keinen Clip hat.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 13.07.2011 um 17:31 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 13.07.2011 um 17:34 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 13.07.2011 um 17:36 Uhr geändert. ]
 
Der_Wanderer   Nutzer

13.07.2011, 16:47 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Ich glaube nicht, dass sich jemand in den Source einlesen will, schon gar nicht bei Assembler. ;-)

Ich verstehe nicht ganz warum du den Clip nicht restaurieren kannst. Wie gesagt, ich versuche das mal zu veranschaulichen, aber dafür brauch ich eine ruhige Minute.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

13.07.2011, 09:53 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

@Holger

Warum würde ein Programmierer einen Refresh erzwingen wollen, wenn das GUI Toolkit das für ihn tut?
Bei modernen Toolkits wie Android gibt es eine solche Möglichkeit meines Wissens nach nicht, aber es fehlt auch nichts. Wenn z.b. ein einem zweiten Thread gezeichnet wird, dann möchte man sicher nicht dazwischenfunken durch einen direkten Draw Aufruf.
Die "Anzeige" ist für die App eine Black Box. Man beschäftigt sich nur mit den Widget Paramtern/Daten. Wie und wann und wo sie gezeichnet werden, ist Aufgabe des Toolkits.
Bei NTUI wird nie sofort gezeichnet, sondern erstmal das Dirty Flag gesetzt. Möglicherweise nehme ich ja viele Änderungen vor, die jedesmal ein Neuzeichnen erfordern würden. In der Regel gehen die Änderungen furchtbar schnell (z.b. eine Farbe ändern => Setzen eines Integers), während das Neuzeichnen im Vergleich furchtbar lange dauert. Erst wenn ich alles gesetzt habe und zurückkehre in den NTUI Code, wird dann neu gezeichnet was "dirty" ist. Die Responsivität leidet darunter nicht, im Gegenteil, wenn mehrfaches Refresh vom Prinzip her verhindert wird ist es immer schön flott.


@AGSzabo
Du braucht keine Clipping flags oder sowas. Jedes Widget kann geclippt werden.

Ich glaube wir reden etwas aneinander vorbei.

Des weiteren denke ich, dass der Aufwand den Tree abzusteigen überschätzt wird. Es ist ja gerade die Tree Struktur, durch die sich die betroffenen Widgets sehr schnell ermitteln lassen, egal ob Mausklick, Refresh etc.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 13.07.2011 um 09:59 Uhr geändert. ]
 
Der_Wanderer   Nutzer

12.07.2011, 22:11 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Hoppla, stimmt. Das OrRectRegion mache ich nur, wenn die Region vorher NULL war. Das ist so eine seltsame Ausnahme, weil NULL zwar kein Clipping macht, aber beim OR/AND sich wie "nichts" verhält.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

12.07.2011, 21:06 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

@AGSzabo:

1.
Ja, aber die Funktion heisst trotzdem OrRectRegion, bildet aber die Schnittmenge. Da hat wohl jemand in der Informatikvorlesung geschlafen, als er die API designed hat.

2.
Dein Konzept setzt dann aber vorraus, dass der App Programmierer 68k Assembler verwendet, oder nicht?
Was mache ich, wenn ich C++, Amiblitz oder AREXX benutze?


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 12.07.2011 um 21:06 Uhr geändert. ]
 
Der_Wanderer   Nutzer

12.07.2011, 21:03 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zitat:
Ja, so macht es Intuition. Ruft man SetAttrs[A] oder SetGadgetAttrs[A] auf, teilt der Rückgabewert mit, ob die Änderung ein visuelles Update erforderlich macht oder nicht. Es bleibt trotzdem dem Aufrufer vorbehalten, die Refresh-Funktion aufzurufen, d.h. er kann auch erst einmal ein Dutzend Änderungen durchführen, bevor er einen visuellen Refresh durchführt.

Sagte ich nicht schon einmal, dass es sich lohnt, die existierenden Lösungen zu studieren, bevor man seine eigene zu machen versucht? ;)

Ja sollte man. Und z.b. ist es schlecht, dem App Programmierer den Refresh auszubürden, weil er es in 90% der Fälle zu selten oder zu oft macht. Der GUI Toolkit Programmierer weis am besten, wann ein Refresh zu tun ist. Und man muss auch keine Return Code dafür missbrauchen, sondern kann einfach das Widget in die "Damage" List setzen, falls noch nicht geschehen. Der Return Code ist dafür zu wichtig.
Bei Events z.b. wird der Return Code normalerweise dazu benutzt um anzuzeigen, ob das Event konsumiert worden ist oder anderen Widgets zur Verfügung steht.

Zitat:
Zitat:
Original von Der_Wanderer:
Alle IDs und Notifys sind bei mir Strings. Da habe ich lange drüber nachgedacht, bin aber auf keine bessere Lösung gekommen.

Es gibt ja auch keine bessere.
Zumindest nicht, wenn man sich nicht auf eine Programmiersprache, für die man z.b. Headerdateien erzeugt, festlegen will.
Und per Hand wollen wir ja im Jahre 2011 keine GUI mehr machen...

Zitat:
Wenn es um Effizienz geht, lässt man das Toolkit eine eigene Hashmap aufbauen, die für jeden String einen kanonischen Eintrag besitzt, durch den jeder String bei der Initialisierung eines Clients (oder dem Laden einer XML-Datei) ersetzt wird.
Dann muss man keine String-Vergleiche anstellen, sondern lediglich die Adressen der Strings vergleichen, da dann ja gleiche Strings immer auf dieselbe kanonische Instanz zeigen.
Ist also exakt genauso effizient wie Integer-Werte.

Ja auch eine gute Idee. Aber wie gesagt, "don't optimize".
Die Strings sind wirklich das letzte, was Performance kostet. Da schlagen die Skin Grafiken um mehrere Zehnerpotenzen mehr zu buche.
Und wenns doch ein Nadelöhr werden sollte, dann hast du ja gezeigt dass man es so effizient wie Integer machen kann.

Zitat:
Nein, es muss beim ersten nicht-transparenten Parent gestarten werden. Der Root wäre nur der worst-case. Ich hatte ja dazu schon oben etwas geschrieben, wie Swing es macht.
Schon richtig. Aber: "don't optimize yet". Kann man alles später noch tun, wenn es zu langsam sein sollte. Aber mal ehrlich, wieviele Layer hat man denn schon?
Normalerweise hat das Fenster einen soliden Hintergrund, alle weiteren Widgets (z.B. Gruppen) sind transparent bis dann irgendwann der Button kommt. Klar kann auch eine farbige Gruppe dazwischen kommen, aber wen interessieren schon zwei RectFill statt einem in so einem schon eher seltenen Fall. Erstmal sollte man sich drauf konzentrieren, dass alles "korrekt" implementiert ist. Sonst verbaut man sich schnell den Weg durch optimieren, z.b. hatte ich am Anfang auch das so gemacht, dass die Hintergrund Farbe ermittelt wird vom Button aus. Als dann aber Skins dazu kamen, hat das nicht mehr geklappt, denn die "Hintergrundfarbe" kann ist dann nicht mehr einfarbig und kann sich wegen Alphatransparenz aus allen Pixel "darunter" zusammensetzen, sodass man gar nicht anders kann als beim Root anzufangen.





--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 12.07.2011 um 21:08 Uhr geändert. ]
 
Der_Wanderer   Nutzer

12.07.2011, 20:51 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

@Thore:

> OR ist schon richtig, ist kein AND, beim AND wäre es sowas wie die
> Schnittmenge, bei OR die Gesamtmenge (Vereinigung)
Wir wollen aber die Schnittmenge, nicht die Vereinigung. Trotzdem heisst der Befehl OrRectRegion.

Wenn Azabo einen Text clippt, damit er nicht aus dem Widget herausgeht, will er die Schnittmenge des bestehenden Clips (der möglicherweise "enger" ist) und dem Text bilden, nicht die Vereinigung, das wäre ja sinnlos.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

12.07.2011, 18:07 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

> Der clip des tabellentitels muß aber die anderen clips zb von views mit berücksichtigen!
Ja sicher, deshalb wird er ja auch draufge-OR-ed (benutze OrRectRegion() allerdings entspricht das meinem Verständnis von AND, aber egal), also verengt.
Wenn die Rekursion eine Stufe nach oben zurückkehrt, ist ja aber die alte Region wieder hergestellt. Dann geht man "nebendran", oder wieder eins höher, so löst sich die Verengung wieder auf bis man wieder beim Root angekommen ist.

Falls du vorhast, transparente Widgets zu haben (z.b. Buttons mit runden Ecken), dann musst du sowieso beim Root anfangen zu zeichnen, da ja der Hintergrund auch neu gezeichnet werden muss, den dein runder Button aber an den Ecken gar nicht kennt.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

12.07.2011, 17:27 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zitat:
Original von AGSzabo:
@Der_Wanderer:

Nee, ich meine die "1" wird vom compiler in eine wertvariable umgewandelt und die wird einem attribut zugewiesen.

Nein. Die GUI wird ja bei mir nicht (notwendigerweise) fest reinkompiliert. Sonst müsste z.B. der GUI Builder die Zielprogrammiersprache kennen.

Alle IDs und Notifys sind bei mir Strings. Da habe ich lange drüber nachgedacht, bin aber auf keine bessere Lösung gekommen. Zumindest nicht, wenn man eine Amiga Shared Library draus machen will die von allen erdenklichen Programmiersprachen genutzt werden kann.

Zitat:
Mein Clipping funktioniert nicht. Könntest du bitte mal schauen ob du mir das noch besser erklären kannst, wie es zB geht?
Ich versuche das mal zu veranschaulichen, später.

Zitat:
Wenn ich von oben anfange, dann nutzt es mir nix den bereich nur zu verengen, denn wenn dann ein benachbartes view gezeichnet werden soll und der clip schon verengt ist, fällt das benachbarte gadget raus.
Das benachbarte Widget ist aber in der Hirarchie nicht drunter, sondern nebendran.

Zitat:
Und wie macht man es, wenn man zusätzlich zu den system clips temporär einen kleinen userclip installieren will, der zb in einer liste den titel abschneidet, wenn er nicht in die spalte passt? Müsste man da nicht hinterher wieder oben anfangen mit dem verengen der clips?
Bei "InstallClipRegion()" bekommst du ja die alte Clipregion als Rückgabe Wert. Bevor eine Funktion zurückkehrt, sollte sie natürlich die alte wieder herstellen. Durch die Rekursion ist so sichergestellt, dass es immer genau stimmt.
Evtl. liegt dein Problem in dem Verständnis der Rekursion?



--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

12.07.2011, 10:36 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Nunja, wenn es ein String ist, dann geht wohl auch "1" ;-)

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

12.07.2011, 09:29 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Achso, du willst das Callback basierend machen. Habe ich mir auch überlegt.

Man kann ja zwei Ansätze verfolgen.

1. Man macht einen Message Loop, d.h. es gibt eine Funktion wie "WaitEvent()", die die Applikation aufruft und darin schläft. Die Funktion gibt dann Events zurück, die der Applikationsprogrammierer vorher gesetzt hat, und kann dann darauf reagieren.
Nicht zu verwechseln mit IDCMP Events, die sollte der App Programmierer niemals zu Gesicht bekommen, schon aus Portabilitätsgründen nicht.
Die App bekommt nur "logische" Events, die eine bestimmte Aktion representieren, nicht ein bestimmtes IDCMP Event eines Eingabegerätes.

Die ID so eines logischen Events ist in NTUI ein String, den ich Notify nenne. Es ist deshalb ein String, weil ich die GUI komplett in XML definierbar machen möchte.

code:
<Button id="MyButton" onClick="button_wurde_geklickt">

...
while (!quit) {
  event = WaitEvent();

  switch(event.notify) {
    case "button_wurde_geklickt":
      <etwas tun wenn der Button gedrückt wurde>
  }
}

return; // end of program


2. Der Message Loop wird versteckt. Die App besteht eigentlich nur aus der Definiton von Callback Funktionen, die auf bestimmte logische Events gesetzt werden. Das ist eigentlich der modernere Approach, aber setzt mehr Erfahrung vom Programmierer vorraus, vor allem wenn es dann Mutltithreaded wird, da eine Callback ja nicht wirklich lange brauchen sollte. Für einen Virenscanner z.b. bräuchte man dann auf jedenfall 2 Threads. D.h. der Programmierer muss das konzept von Threads und vor allem Threadsafe verstanden haben. Je nach Programmiersprache wird das auch schwer zu verwenden, z.b. Basic.

code:
<Button id="MyButton">
...

SetAttr("MyButton",ATTR_ONCLICK,?button_wurde_geklickt);

void button_wurde_geklickt(object *eventobject) {
  <etwas tun wenn der Button gedrückt wurde>
}

EnterEventLoop();

return; // end of program


Ich denke mal, dass NTUI beides unterstützen wird. Momentan wird aber nur Event Loop unterstützt.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 12.07.2011 um 09:36 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 12.07.2011 um 09:38 Uhr geändert. ]
 
Der_Wanderer   Nutzer

11.07.2011, 23:06 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Dein Program "schläft" ja normalerweise in der GUI Engine, in soetwas wie "WaitEvent()". Wenn ein Event kommt, wird der "Focus" an die Applikation übergeben indem diese Funktion zurückkehrt. Dort kann dann die Applikation nach Lust und Laune an den Widgets rumschrauben, diese werden jedoch nicht sofort gezeichnet, sondern nur "dreckig" gemacht.
Die Applikation gibt dann den Focus möglichst schnell wieder zurück, indem es in WaitEvent() wieder zurückkehrt.
Dann werden erstmal alle dreckigen Widgets neu gezeichnet, und dann wieder nach Events gelauscht.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

11.07.2011, 22:19 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Ich würde möglichst viel dem Widget Code selbst überlassen, denn es weis am besten wie es klippen muss. Ein SetAttr() macht bei mir ein Widget "damaged" (bzw. in NTUI heisst das "dirty"). Erst nachdem der Focus zur Engine zurückkehrt, wird es dann neu gezeichnet. So vermeidet man multiple Refreshs beim setzen vieler Attribute, wie oben schon erwähnt.

Generell kann ich tatäschlich von zu viel Optimierung abraten. Besser man denkt sich gute Datenstrukturen und Algorithmen aus, und implementiert das sauber. Am Ende kann man sich dann anschauen, wenns fertig ist, an welchen Ecken und Enden es zu langsam ist. Nur dann sollte man optimieren, denn optimieren bedeuted immer spezialisieren und dadurch einschränken. Oft liegt das Nadelöhr auch ganz wo anders, als man am Anfang des Projekts vermuten würde.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

11.07.2011, 21:27 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Zitat:
Original von AGSzabo:
@Der_Wanderer:

Bei mir heisst das einfach nur view, weil das element mit den scrollern dazu diese view benutz. es sind zwei getrennte klassen, von denen die eine die andere benutzt. die scroller selbts sind auch extra klassen, die vom "scrollview" benutzt werden.

Bei mir ist es so, dass der ScrollView eine Content-Area hat und, falls nötig, Scroller initialisiert und diese zeichnet als Sub-Objekte. Er hat also 3 Subobjekte, und zwar den Inhalt (was auch immer das ist) und zwei Scroller. Die Scroller sind immer da, nur "Gone", falls man sie nicht benötigt, d.h. der Inhalt kleiner oder gleich dem ScrollView (minus Border, falls vorhanden) ist.

Zitat:
Ich habe nicht ganz verstanden, bei dir können views in views sein usw? Es wird immer der ganze baum abgewandert beim zeichnen?
Die können beliebig geschachtelt sein, ja. So wie TabViews etc.
Alles kann man beliebig verschachteln, weil ja alles rekursiv aufgebaut ist. Wenn eine Verschaltelung funktioniert, dann automatisch auch N Verschachtelungen.

Zitat:
Wenn ein objekt nur einen teil von sich neu zeichen möchte, zb nur den rahmen eines buttons im geklickten also inversen zustand?
Ja, bei einigen Widgets ergibt sich daraus tatsächlich etwas Kopfzerbrechen.
Aber bei den allermeisten Widget ist das so, dass sie sich Brute Force neu zeichnen. Zu optimieren ist das hier zu viel Geraffel was nichts bringt. Bedenke, dass bei NTUI z.b. auch Skins unterstützt werden, bei denen das komplette Hintergrundbild eines Buttons ausgetauscht wird, da kann man also sowieso nicht anders als alles neu zeichnen.
Man muss nur aufpassen, dass man das neu Zeichnen nicht sieht. Bei Skins geht das nur durch Double-Buffering, korrekter gesagt "Offscreen Bitmaps", bei den prozeduralen Looks habe ich das so geschickt gemacht, dass kein Pixel mehrmals bemalt wird, und somit flackert auch nichts.

Zitat:
was macht ntui dann? Button hier ist nur ein beispiel, es könnten ja komplexere Objekte sein, bei denen es sich evtl rentiert nicht alles neu zu zeichnen.
Ja, z.b. ein TabView, das beliebig komplexen Inhalt haben kann.
Wenn das den Focus verliert ändert sich nur der Rahmen.
In diesem Fall überlädt der TabView die Funktionen in denen nur der Rahmen sich ändert (z.b. "OnFocus"), und zeichnet nur den Rahmen neu.
Die Eltern-Implementation der Funktionen ist normalerweise ein simples Redraw, was ja immer funktioniert, nur manchmal etwas unoptimiert ist.

Aber wie Michael Jackson schon sagte:

"The First and Second Rules of Program Optimisation:
1. Don’t do it.
2. (For experts only!): Don’t do it yet."

Die meisten Bugs und Programmier-Sünden werden im Namen der Optimierung begangen.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 11.07.2011 um 21:43 Uhr geändert. ]
 
Der_Wanderer   Nutzer

11.07.2011, 17:28 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Sowas hier meinst du vermutlich:

Bild: http://www.hd-rec.de/pics/ntui_status25.png

Das ist übrigends eines der mächtigsten Widgets überhaupt. Ich habe es "ScrollView" genannt. z.b. brauchst du für Listviews, Textboxen, ChatLogs, Bilder, Fließtext etc. alles gar keine eigenen Scroller implementieren, du packst sie einfach in einen ScrollView und lässt sie so groß werden wie sie sein wollen.
Der ScrollView erledigt das scrollen für dich.

Hint: Das erste Element unterhalb eines Windows kann auch ein (borderless,auto-scroller) ScrollView sein, in dem sich der Rest des Fensters befindet. Somit fängt das Fenster automatisch zu scrollen an, wenn es nicht auf den Bildschirm passen sollte, z.b. wenn jemand auf 320x256 springen würde. Sehr elegant, so ein ScrollView.


--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 11.07.2011 um 18:02 Uhr geändert. ]
 
Der_Wanderer   Nutzer

11.07.2011, 17:24 Uhr

[ - Direktlink - ]
Thema: OOP-GUI Systeme und Content-Clipping
Brett: Programmierung

Bei NTUI ist das so gelöst, dass man (der Nutzer der API) grundsätzlich nur "von oben", also dem Root (normalerweise ein Fenster) zeichnen kann.

Allerdings kann man jedem Refresh eine Clip-Region mitgeben, die Objekte "nach unten" hin auch weiter verengen können.

Objekte testen dann erstmal, ob sie überhaupt drin liegen, wenn nicht, springt es sofort wieder zurück.
Der Overhead, "von oben" zu beginnen, ist zu vernachlässigen, im Vergleich zu dem Zeichnen des eigentlichen Objekts. (Tiefe des Baums ist ja nur O(log n), n = Anzahl der GUI Elemente.

Will ich also ein einzelnes Objekt refreshen (dafür gibts natürlich ein Convenient-Stubb), dann nimmt sie den Root und setzt die ClipRegion auf die Boundaries des zu refreshenden Objekts, und führt dann ein ganz normales, globales Refresh durch.

Vorteil: Es gibt nur eine einzige Funktion zum Zeichen, egal welches Objekt, egal ob beim initialen Zeichen oder partiellen Refresh (Simple Refresh Windows), bei Data/Status-Updates von Objekten etc.

Ein weiterer Vorteil ist, dass man nicht sofort neu zeichnen muss, sondern kann die betroffenen Objekte erstmal als "damaged" markieren, und zeichnet erst neu, wenn der User der GUI Engine wieder den Focus gibt. Vorteil: Setze ich 1000x den Wert eines Objekts neu, wird es trotzdem nur 1x gezeichnet => keine lästigen Refresh Orgien z.b. beim Befüllen eines Lisviews oder beim Solid-Resizing.

Die eigentliche Zeichenfunktion eines bestimmten Objekts darf man nicht von aussen aufrufen, sondern muss immer durch diesen Mechanismus hindurch.
(bei NTUI ruft der API User eigenlich nie die Zeichenfunktionen auf, da NTUI das alles bereits regelt, es sei den er möchte in einen eigenen RastPort zeichnen, z.b. für einen GUI Builder oder Skin Vorschau).


P.S: Mit "virtual" hat das nichts zu tun. So ein ScrollView ist ein ganz normales Widget wie alle anderen auch.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ Dieser Beitrag wurde von Der_Wanderer am 11.07.2011 um 17:59 Uhr geändert. ]
 
Der_Wanderer   Nutzer

01.06.2011, 23:01 Uhr

[ - Direktlink - ]
Thema: GUI Markup Language
Brett: Programmierung

NTUI ist selbst momentan (noch) in Amiblitz3 geschrieben. Die Library wird man aber natürlich in jeder anderen Sprache ganz normal nutzen können. Es steht aber zwecks Portierbarkeit noch ein C Port an.

Was ich meinte ist, dass der XML Code keinen Quelltext erzeugen sollte (wie z.B. C oder ASM), sondern interpretiert werden sollte.
Dadurch ergibt sich eine enorme Flexibilität. Anders wären z.b. auch die GUIs der DSP Effekte in HD-Rec nicht machbar, da ich ja zur Compilezeit von HD-Rec noch nicht weis welche DSP Effekte es geben wird. Und es soll ja nicht jeder DSP Effekt seine eigene GUI Engine mitbringen.

NTUI ist natürlich erstmal eine Shared Library mit Funktionen wie
code:
ntui_BeginWindow("Demo");
  ntui_Label("Test");
  ntui_Button("myButton","Click me!");
ntui_EndWindow();


aber man kann das ganze auch in XML definieren:

code:
<Window title="Demo">
  <Label text="Test">
  <Button text="Click me!" id="myButton");
</Window>

und dann

ntui_CreateFromXML(const char* xml);

bzw.

ntui_CreateFromXMLFile(const char* filename);

aufrufen, was das gleiche bewirkt.
So solltest du das auch machen.
Pointer auf die Widgets holt man sich über die ID, die ein String ist. Oder man verzichtet ganz auf Pointer und interagiert mit der GUI komplett über die IDs. In NTUI geht beides.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

01.06.2011, 22:08 Uhr

[ - Direktlink - ]
Thema: GUI Markup Language
Brett: Programmierung

NTUI macht (fast) genau das. Allerdings ist es relativ unsinnig, 68K ASM Code zu erzeugen. Der "Compiler" sollte lediglich ein Parser für den XML Code sein und zur Laufzeit interpretieren und die GUI aufbauen. Das ist ja gerade der Vorteil an Scripting, dass es nicht zur Compilezeit bereits existieren muss.

Bild: http://www.hd-rec.de/pics/ntui_skin1.png
--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

06.01.2011, 22:25 Uhr

[ - Direktlink - ]
Thema: teiltransparenz
Brett: Programmierung

@Holger

Stimmt, erst Shiften und dann Addieren ist nicht das Gleiche, es geht ein Bit Genaugikeit verloren, man erhält also 21Bit Qualität statt 24bit. Wenn es aber nicht um Grafikverarbeitung geht, sondern nur um die Darstellung von z.b. Schatten etc. ist das durchaus verschmerzbar.
Es ist schon um einiges schneller, allerdings ist das ReadPixelArray der größte Broken.


Das mit der For-Schleife sollte der Optimizer eigentlich erkennen, da die Variablen Schleifeninvariant sind. Aber natürlich ist sicher immer noch sicher.

Bei guten Kompilern habe ich aber gemerkt, man sollte nicht versuchen clever zu sein, denn die Kompiler sind auf Standard Situationen optimiert.
Wenn man anfängt mit vielen Tricks zu arbeiten, "pfuscht" man dem Optimizer quasi dazwischen und es kann sogar langsamer werden.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
Der_Wanderer   Nutzer

06.01.2011, 10:22 Uhr

[ - Direktlink - ]
Thema: teiltransparenz
Brett: Programmierung

Das ist im groben so ähnlich wie ich es mache bei Alphatransparenz, wie im Screenshot oben.

Allerdings das hier:
MyArray[i]=(MyArray[i]+TempArray[i])>>1;

ist problematisch weil es überlaufen kann. Man müsste zuerst beide herunter Shiften oder vorher nach short oder int casten.

Es geht aber noch schneller, man kann auch gleich 4 Bytes holen, die unteren bits wegmaskieren, shiften und addieren.

Wobei aber in dem Fall das Nadelöhr das Read/Write Pixelarray ist.

--
--
Author of
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de

 
 
Erste 2 3 4 5 6 -7- 8 9 10 11 12 >> Letzte Ergebnisse der Suche: 1229 Treffer (30 pro Seite)

Suchbegriffe
Schlüsselwörter      Benutzername
Suchoptionen
Nur in diesen Foren suchen
   nur ganze Wörter
Nur Titel anzeigen
alle Treffer anzeigen

.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.