[WPF] Design van een graph editor

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Topicstarter
Ik mag zo af en toe graag eens wat hobbyen, en nou heb ik onlangs m'n soft synth genaamd "Machinery" weer eens afgestoft. Nou was de UI daarvan oorspronkelijk ontworpen mbv de rauwe win32 API, en gezien mijn kennismaking met WPF van afgelopen jaar leek het mij wel een goed idee om de boel eens volledig om te gooien. Echter, mijn kennis van WPF is nog lang niet op niveau, dus ik vroeg mij af hoe ik het volgende aan moest pakken.

De kern van mijn app bestaat uit 'machines' die aan elkaar te koppelen zijn. Zo'n machine heeft een optioneel aantal inputs en outputs, en de output van de ene machine is weer te knopen aan de input van een ander. Voor diegene die bekend zijn met audio apps, dit is vergelijkbaar met programma's als Reason en Buzz, maar eigenlijk is dat niet eens zo interessant - feitelijk kun je het gewoon zien als een graaf, waarin een Machine een node is en een verbinding tussen de machines een edge. Hier een screenshot van mijn oude win32 implementatie:

Afbeeldingslocatie: http://oisyn.nl/pics/machinery2.png

Nou zou ik zoiets wel gewoon kunnen implementeren in WPF, maar ik wilde het graag goed aanpakken en ik heb een belangrijke eis: een machine moet zelf zijn eigen view kunnen implementeren. Onder win32 was dit vrij simpel, geef een HDC mee aan een Draw() method op een interface die de machine implementeert zodat ie gewoon zijn eigen shit kan tekenen, en verder had ik nog een HitTest() method zodat de machine kon rapporteren of op die plek een input of output of z'n caption staat, zodat de app de inputs en outputs aan elkaar kon verbinden of de machine kon selecteren en verplaatsen.

Nou is de Draw() in WPF natuurlijk een no-go, maar hij zou wel een DataTemplate oid aan kunnen leveren die je kunt gebruiken om z'n visual tree te instantieren. De HitTest() is nog steeds mogelijk, maar dit lijkt me niet de WPF-manier om dingen te doen. Is het niet netter om specifieke controls of standaard controls met specifieke attached dependency properties in de visual tree te hebben, zodat de app weet wat ie ermee kan doen? Wat ik dus iig wil kunnen is een machine selecteren en draggen door op z'n caption te klikken, en natuurlijk outputs met inputs verbinden op het moment dat je vanaf zo'n output/input begint te click-draggen. Het lijkt me logisch dat de machine view niet zelf verantwoordelijk is voor die logica, maar hij moet bijvoorbeeld wel in staat zijn om een simpele bitmap te tekenen en dat ik dan op een of andere manier te weten kom of er op zo'n input geklikt is. Of is er wellicht nog een compleet andere manier om dit probleem te tacklen?

Hoe zouden jullie zoiets aanpakken?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
.oisyn schreef op dinsdag 16 augustus 2011 @ 23:15:
Hoe zouden jullie zoiets aanpakken?
Prism

Elke conceptuele machine is dan een Prism module, die zijn eigen models, views, etc. mbv IoC en DI (MEF of Unity) kan injecteren en configureren. Maakt alles ook nog eens super plugbaar. Individuele machine views kun je natuurlijk laten overerven van een specifieke base view die basis logica zoals drag/drop implementeert.

Alternatief is wss. inderdaad om MVVM toe te passen en elke individuele machine een eigen view model te geven, wat een eigen data template door kan geven voor het renderen v/d interne opmaak.

[ Voor 30% gewijzigd door R4gnax op 17-08-2011 00:01 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Topicstarter
Bedankt voor je input, maar dat is niet echt een antwoord op mijn vraag. Het gebruik van een compleet framwork voor mijn beoogde doel lijkt me wat overkill, en overcompliceert zowel mijn eigen code alswel die van degene die een machine implementeert :). Ik wil ook gewoon WPF leren, en niet nog eens een 3rd party library die daarop voortborduurt ;)
Alternatief is wss. inderdaad om MVVM toe te passen en elke individuele machine een eigen view model te geven, wat een eigen data template door kan geven voor het renderen v/d interne opmaak.
Dat is globaal wat ik omschreef, maar het doel van mijn topic was nou juist om hier in detail op in te gaan ;). Een concreet voorbeeld: ik ben een endpoint van een verbinding aan het verslepen met de muis, hoe kom ik te weten dat ik boven een input connector aan het hoveren ben met de muis in een control die volledig zijn eigen visual tree definieert?

Maar na nog eens wat in-depth artikelen over attached dependency properties gelezen te hebben denk ik dat dat the way to go is. Door bijv. een IsStreamConnector attached property te hebben op de root UIElement die de visual tree van een enkele input of output definieert, kan ik bepalen dat een endpoint van een verbinding daar te droppen is.

[ Voor 30% gewijzigd door .oisyn op 17-08-2011 00:37 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
.oisyn schreef op woensdag 17 augustus 2011 @ 00:28:
[...]

Bedankt voor je input, maar dat is niet echt een antwoord op mijn vraag. Het gebruik van een compleet framwork voor mijn beoogde doel lijkt me wat overkill, en overcompliceert zowel mijn eigen code alswel die van degene die een machine implementeert :). Ik wil ook gewoon WPF leren, en niet nog eens een 3rd party library die daarop voortborduurt ;)
Je kunt ook enkel het IoC / DI gedeelte van Prism gebruiken. Reden dat ik het voorstelde is omdat elke module zijn eigen startup kan managen en zijn eigen dependencies kan registreren. Je inverteert daarmee dan ook de control flow van WPF, waar XAML pages / views normaal centraal staan. Op die manier hoeft een view niet zichzelf te managen (door o.a. zelf ergens een view model vandaan te halen), maar kun je op een wat gestructureerder manier (bijv. met view mediators) werken.

Je kunt echter wss. zelf beter beoordelen of het het waard is om dat stuk van Prism te gebruiken in de context van de scale van jouw applicatie. :)

  • Teunis
  • Registratie: December 2001
  • Laatst online: 01-09 21:00
ItemsControl + Canvas website: http://drwpf.com/blog/itemscontrol-a-to-z/
als je echt basic wil houden kan allemaal met canvas ook. ;)

ps niet echt duidelijk waar je nu op stuk loopt, Model, View koppeling daar tussen/

Please nerf Rock, Paper is fine. Sincerely yours, Scissor.
GW2:Teunis.6427


Acties:
  • 0 Henk 'm!

Verwijderd

Dit moet je inderdaad gestructureerd aanpakken, anders zie je voordat het af is door de bomen het bos niet meer. Ik heb eerder in WPF iets dergelijks gebouwd (een soort van Class designer, bijv visio). Ik kan je vertellen, het moeilijkste gedeelte van dit geheel is het implementeren van de connectoren (pathing algoritme).

Mijn aanbevelingen:
- MVVM (omdat het kan)
- Een eigen subclass van ItemsControl, met een Canvas als ItemsPanel. Bind de X en Y aan ViewModel properties. (dit is ligt niet meteen voor de hand ivm ItemContainer)
- Aangezien je connectoren naar een specifiek deel van de knoop in je graaf leiden zul je een methode moeten maken die de positie van een bepaald punt kan opvragen aan de hand van een specifieke ViewModel (InputViewModel ofzo), ook zul je deze moeten herordenen (als je wilt voorkomen dat connectoren elkaar kruisen)

In de eerdere posts zie ik veel over Prism etc, dit heeft (bijna) niets te maken met de moeilijkheid van je vraagstuk.

Edit: http://www.codeproject.co...iagramDesigner_Part1.aspx zal je een heel eind op weg helpen.

[ Voor 5% gewijzigd door Verwijderd op 26-08-2011 01:08 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 11:17

.oisyn

Moderator Devschuur®

Demotivational Speaker

Topicstarter
Het vinden van een mooi pad vind ik niet zo'n issue, ze mogen elkaar best kruisen of onder componenten langs lopen. Gezien de aard van hoe componenten in de praktijk verbonden worden vormt dat ook niet zo snel een probleem (de edges lopen niet kriskras, wat je bij een klassediagram wel snel hebt).

Nee, het specifieke probleem zit 'm in de extensibility. Een node kan zijn eigen visual tree instantieren, maar hoe weet het omliggende component dan waar in die tree de aansluitpunten zitten? Overigens ben ik gewoon gegaan voor attached dependency properties. Een node zet gewoon specifieke attributen in z'n xaml, en bij een mouse event kijk ik dan of de sender zo'n attribuut heeft.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1