NSA - Non Solo Amiga

SOFTWARE => Linguaggi di programmazione e scripting => Topic aperto da: Allanon - 17 Agosto 2011, 12:26:16

Titolo: Interfacce e comportamento pulsanti
Inserito da: Allanon - 17 Agosto 2011, 12:26:16
Sto lavorando ad una nuova versione della scuilib e stavo riproducendo il comportamento dei pulsanti, in pratica ho reimplementato il comportamento:

1. Premo il pulsante (senza rilasciare il LMB) -> disegno il pulsante in stato premuto
2. Mantenendo il LMB premuto esco dall'area del pulsante -> disegno il pulsante in stato normale
3. Sempre mantenendo il LMB premuto rientro nell'area -> disegno il pulsante in stato premuto

E fin qui tutto bene... poi mi sono messo ad osservare il comportamento della gui di seven (ma sicuramente sarà il medesimo di tutte le altre versioni di windows) e mi sono accorto che:

1. Premo il LMB in un'area non attiva
2. Trascino il mouse sempre con il LMB premuto su un pulsante -> windows disegna il pulsante evidenziato
E' giusto? Oppure non dovrebbe disegnare nulla dal momento che il mouse è stato premuto fuori dall'area attiva?

Altro dubbio:
1. Premo il LMB su un pulsante e mantengo premuto -> windows disegna il pulsante premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante normale
3. Rientro nel pulsante sempre con il LMB premuto e poi lo lascio -> windows disegna il pulsante premuto e poi parte l'evento
e qui va bene però se...

1. Premo il LMB su un pulsante e mantengo premuto -> windows disegna il pulsante premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante normale
3. Lascio il LMB, e poi lo ripremo in un'area non attiva
4. sempre mantenendo il LMB premuto entro sul pulsante del punto 1 -> windows mi disegna il pulsante evidenziato
5. Lascio il LMB -> windows lancia l'evento
A me questo comportamento non sembra proprio corretto, primo percè ho lasciato il LMB fuori dal pulsante e poi perchè mi lancia l'evento su un rilascio del LMB in seguito ad un evento di evidenziazione e non di pressione...

Ditemi voi, forse sono io che prendo un abbaglio ma se devo riprodurre questi comportamenti è bene che sappia precisamente cosa è giusto e cosa no  :D
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 17 Agosto 2011, 19:03:17
Ti secchi se spengo un po' il cervello e ci rifletto non appena sono più tranquillo e riposato?
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 17 Agosto 2011, 19:07:36
Windows lancia i seguenti eventi:

- Alla ricezione del focus (che può essere dato da tastiera, premendo TAB)
- Alla perdita del focus
- Alla presenza del puntatore (mouse over)
- All'uscita del puntatore (mouse leave)
- All'inizio della pressione
- Alla fine della pressione
- Al click (combinazione di pressione + fine pressione + delay > di N ms, anche lasciando il focus, il delay dipende dalle impostazioni di doppio click dell'OS)
- Al doppio click (combinazione di pressione + fine pressione + delay < di N ms + pressione + fine pressione)
NB: Se non è agganciato alcun listener per l'evento doppio click, puoi omettere il delay nel click in modo da rendere più reattiva la GUI.

Il codice che agganci a tali eventi dipende dalla particolare applicazione, quindi da scelte che stanno al di fuori della libreria della GUI.

Una libreria di GUI dovrebbe rilasciare questi eventi, e dare al programmatore il compito di scegliere se scatenare del codice al click oppure alla pressione, oppure al mouse over, ecc...
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 17 Agosto 2011, 21:46:17
@cdimauro
figurati, fai con comodo :)

@TheKaneB
Citazione
- Alla ricezione del focus (che può essere dato da tastiera, premendo TAB)
- Alla perdita del focus
- Alla presenza del puntatore (mouse over)
- All'uscita del puntatore (mouse leave)
- All'inizio della pressione
- Alla fine della pressione
- Al click (combinazione di pressione + fine pressione + delay > di N ms, anche lasciando il focus, il delay dipende dalle impostazioni di doppio click dell'OS)
- Al doppio click (combinazione di pressione + fine pressione + delay < di N ms + pressione + fine pressione)
Ma la ricezione del focus non è equivalente all'evento mouse over? Quando il mouse va su un pulsante questo non riceve anche il focus?
Stesso discorso per perdita focus & mouse out
Per il resto ho implementato:
- Mouse Over
- Mouse Out
- On Pushed (che poi è l'evento standard quando il pulsante viene rilasciato)
- On Down (lancia l'evento appena il pulsante viene premuto e non al suo rilascio)
- On Drag (se il gadget prevede il dragging l'evento viene scatenato al termine del dragging)
- On Drag Out (sempre se il gadget lo prevede l'evento viene scatenato se il dragging termina al di fuori della finestra di appartenenza)

Citazione
Il codice che agganci a tali eventi dipende dalla particolare applicazione, quindi da scelte che stanno al di fuori della libreria della GUI.
Si, si questo è palese :)

Una tipica creazione di un pulsante senza specificare tante opzioni è:
Codice: [Seleziona]
mygad = HGui.Gadget:new(#HGUI_BUTTON_GADGET, { caption = { "BUTTON", "YEAH!" },
                                               actions = { onpushed = EventTester },
                                               name = "MyGADGET",
                                               window = mywin3 })
<EventTester> è la funzione fuori dalla libreria Gui che il programmatore aggancia all'evento.

Cmq più che altro chiedevo un chiarimento riguardo il "behaviour" che ho descritto, perchè a me sinceramente quel comportamento sembra più una roba buggata, e non vorrei riprodurre anche i bug nella mia Gui library  :D



Piccolo test compilato per windows:
(http://http://img692.imageshack.us/img692/9554/samplehgui.png)
Box, Group, Label, Vertical Divider, Horizontal Divider, Button
Il tutto già con il ridimensionamento e il sistema dei pesi "alla MUI" funzionante :P
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 18 Agosto 2011, 13:52:21
Il Focus non coincide quasi mai con il mouse over, ma con il mouse press.

In Windows un pulsante con focus è circondato da un rettangolo tratteggiato. Puoi cambiare il focus anche da tastiera. Inoltre gli stati del mouse dovrebbero essere separati dagli stati del pulsante, quindi devi prevedere sia il mouse press che il get focus, in modo da consentire lo sviluppo di interfacce senza mouse (ad esempio usando un touchscreen o un telecomando).
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 18 Agosto 2011, 14:02:36
Quindi got focus e lost focus sono scatenati solo dalla tastiera? Quando il pulsante viene attivato da tastiera genera un evento click?

Scusa se ti tartasso ma sono un po' a digiuno di eventi Windows :-)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 18 Agosto 2011, 14:11:53
Sono scatenati dal focus :D

Quindi sia da tastiera che da mouse.
Non deve spaventarti lo scatenamento simultaneo di più eventi. Anzi, è bene che gli eventi complessi siano suddivisi in più sottoeventi semplici.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 18 Agosto 2011, 14:15:56
No no, non mi spaventa affatto è che non ho ben chiara la differenza fra get focus e mouse over, a meno che la differenza stia solo nel fatto che il mouse over sia generato solo ed esclusivamente del mouse ma per il resto siano identici :-)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 18 Agosto 2011, 14:29:56
mouse over ti dice SOLO che il puntatore è sopra il pulsante, quindi è un evento grafico.

got focus, invece, ti dice che il pulsante corrente è interessato (cioè è un target) a ricevere gli eventi correnti provenienti dall'utente. Tali eventi sono quelli di scrolling, click, gli eventi della tastiera, ecc...

Guarda ad esempio Google Chrome. Quando invii un messaggio su questo forum, noterai che il riquadro selezionato ha un bordo arancione, e tale riquadro cattura gli eventi dalla tastiera. Puoi dare il focus ad un altro riquadro cliccandoci o premendo ripetutamente il tasto Tab o Shift + Tab. Il focus dice quale elemento riceve gli eventi dell'utente, mentre il mouse over è limitato all'interazione con il mouse, ed è solo un evento grafico, utile ad esempio per far cambiare un colore o far spuntare un tooltip.

La tua libreria quindi dovrà sapere in ogni momento qual è l'oggetto che detiene il focus, per inviargli correttamente gli eventi, e tale oggetto dovrà essere avvisato quando acquista o perde tale focus.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 18 Agosto 2011, 14:33:36
Ok, ok, tutto chiaro adesso :-)
E' che sto caldo mi rallenta la "brocca", grazie per la spiegazione  :)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 19 Agosto 2011, 16:01:57
Nessuno mi ha ancora detto se secondo voi questo comportamento è corretto:
Citazione
1. Premo il LMB su un pulsante e mantengo premuto -> windows disegna il pulsante premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante normale
3. Lascio il LMB, e poi lo ripremo in un'area non attiva
4. sempre mantenendo il LMB premuto entro sul pulsante del punto 1 -> windows mi disegna il pulsante evidenziato
5. Lascio il LMB -> windows lancia l'evento
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 19 Agosto 2011, 16:39:59
don't know
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 19 Agosto 2011, 20:09:05
Citazione da: "Allanon"
Nessuno mi ha ancora detto se secondo voi questo comportamento è corretto:
Citazione
1. Premo il LMB su un pulsante e mantengo premuto -> windows disegna il pulsante premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante normale
3. Lascio il LMB, e poi lo ripremo in un'area non attiva
4. sempre mantenendo il LMB premuto entro sul pulsante del punto 1 -> windows mi disegna il pulsante evidenziato
5. Lascio il LMB -> windows lancia l'evento
Non è corretto. Il punto 3) impedisce di generare eventi per il pulsante, perché l'azione non è iniziata nella sua area.

L'unica cosa può essere generata è l'evento di mouse over quando sei nel punto 4. Nient'altro.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 19 Agosto 2011, 21:36:58
Infatti io avevo proprio questo dubbio, quindi è un bug. Ho fatto ulteriori prove e mi si verifica solo con PSPad (un text editor), per la precisione con la sua toolbar.
Grazie per la conferma, adesso vado più tranquillo :)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 19 Agosto 2011, 22:36:59
E' un bug sicuramente, perché se prendi una finestra di Windows che ha un pulsante (chessò, le Proprietà di un disco rigido) e provi a eseguire le operazioni che hai descritto, ti rendi conto che non funziona così.

Tra parentesi, uso anch'io PSPad (ma di un paio di versioni fa. Le ultime due hanno strani bug che corrompono la memoria del processo), ma non ho mai fatto caso a questo comportamento anomalo.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 19 Agosto 2011, 22:53:26
Io sto usando la 4.5.4(2356) ma a parte questa cosa strana della tool bar non ho avuto altri malfunzionamenti, e sai che lo uso come editor principale per programmare, per me è uno dei migliori editor free che ci sono in giro, peccato che non hanno ancora implementato il fold/unfold delle funzioni :)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 19 Agosto 2011, 23:05:22
Mi sono fermato alla 4.5.2 (2241); comunque non so come riprodurre quei fastidiosi bug. So solo che tornando alla 4.5.2 non si sono più presentati, per cui mi tengo quella.

Comunque lo uso solo come editor di testo. Per sviluppare in Python o Java uso NetBeans. Per C# ovviamente Visual Studio, come pure per C e C++. Altro per adesso non uso.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 20 Agosto 2011, 23:31:55
Vediamo se stavolta mySQL mi cancella il post  :D

Allora, sempre nel contesto della mia libreria GUI, sono alle prese con la classe <button>, messo in chiaro il discorso degli eventi e del focus (grazie ancora Antonio  ;) ) avevo un'altro dubbio.

Ho previsto la possibilità di inserire nei pulsanti delle icone con i vari allineamenti e con l'opzione di "sistemare" il testo per non far sovrapporre i due elementi. Inoltre ho previsto la possibilità di inserire delle immagini vettoriali e quindi scalabili con la dimensione del pulsante, per il momento in un formato custom molto semplice (poi vedremo), il mia domanda è: ha senso dare la possibilità di inserire tutti e tre gli elementi nel pulsante? Ossia icona, immagine vettoriale e testo? Io credo di non aver mai incontrato pulsanti con all'interno sia una bitmap che un'immagine vettoriale, ma volevo sapere se voi avete incontrato questa possibilità e se entrambi gli elementi grafici sono realmente necessari o se è sufficiente uno dei due assieme ad un eventuale testo.

Lo so che vi stresso, ma a 'sto giro vorrei scriverla per bene questa libreria  8-)
Magari nei crediti ci metto anche NSA  :)
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 21 Agosto 2011, 01:57:50
generalmente i pulsanti hanno una sola immagine + testo.

L'immagine può essere a sua volta vettoriale o bitmap. Questo si può implementare avendo una classe generica Image, e le due derivate Bitmap : public Image e Vectorial : public Image.

Non ho mai visto pulsanti con 2 o più immagini dentro, e sinceramente non ne ho mai sentito il bisogno.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 21 Agosto 2011, 07:16:10
Se vi può consolare, io ho avuto più volte l'esigenza d'infilare un intero pannello con informazioni, immagini, e addirittura altri bottoni, all'interno di un Button (classe di WPF/Silverlight) su Windows Phone 7 (e presto con WPF, perché devo realizzare un'applicazione per Windows dotata di GUI per l'ultimo lavoro che ho preso).

Ad esempio, devo visualizzare una lista di file o cartelle con alcuni loro attributi (nome, timestamp di creazione, chi l'ha creato, dimensione per i file) e un paio di bottoni per cancellare l'elemento o espandere il pannello visualizzando dei commenti a esso annessi. Il click su questo pannello serve, invece, ad aprire una pagina per visualizzarne il contenuto.

In generale su WPF/Silverlight i Button sono in grado di "inglobare" un oggetto qualunque, e di "renderizzarlo" opportunamente. Normalmente è una stringa, che viene "incastonata" in un pannello predefinito internamente che è costituito da un oggetto border che all'interno ha poi un oggetto TextBlock che si occupa di renderizzare la stringa. Ma con Button, come pure con qualunque altro controllo di questi framework, è possibile ridefinire completamente il template (si chiama così in gergo) associato che specifica dettagliatamente quali elementi visualizzare, in che modo, quali attribuiti vanno "prelevati" dalla classe Button, e il tutto per ogni possibile stato (disabilitato, abilitato, con focus, clickato), ed eventualmente con specifici effetti di transizione (anche molto complessi) quando si passa da uno stato all'altro.

Tutta questa flessibilità deriva da una geniale gerarchia di oggetti che è stata pensata per evitare di dover estendere spesso una classe per realizzare un componente che abbia determinate caratteristiche (per lo più visive / comportamentali). In genere si cambia lo stile e/o il relativo template (in realtà ce ne sono due: uno per il binding dei dati, e un altro per specificare accuratamente ogni singolo aspetto del controllo, ed è quello di cui ho parlato prima).

Ovviamente anch'io realizzo nuovi controlli, anche derivati da Button, quando si serve, sia chiaro. Solo che lo faccio raramente.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Agosto 2011, 07:49:36
Ok, quindi secondo il concetto "meglio una feature in più che una in meno" darò la possibilità di inserire anche un'immagine vettoriale con i relativi allinamenti.

@cdimauro
La lib che sto creando permette a qualsiasi controllo di avere dei child, quindi anche all'interno di un pulsante posso inserire qualsiasi altro controllo. Per gli effetti di transizione Hollywood è veramente messo bene e sarà una bazzecola inserirli alla fine quando tutto funzionerà a modino :-)
Dovrò semplicemente aggiungere un paio di campi per il controllo degli effetti e sostituire il comando DisplayBrush con DisplayBrushFX il tutto appoggiandomi ad un'altra libreria che ho scritto tempo fa per gestire le transizioni in maniera asincrona  :P
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 21 Agosto 2011, 09:06:09
Ottimo. Comunque io non metterei la possibilità di inserire un'immagine, di qualunque natura essa sia.

Un Button nel suo uso normale prevede soltanto una stringa da visualizzare, per cui il contenitore classico dovrebbe prevedere un controllo Label/TextBlock che la visualizzi.

Se il programmatore ha bisogno di inserire anche un'immagine (o soltanto un'immagine), può benissimo sostituire il contenitore standard con uno ad hoc allo scopo.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Agosto 2011, 09:47:49
Citazione da: "cdimauro"
Ottimo. Comunque io non metterei la possibilità di inserire un'immagine, di qualunque natura essa sia.

Un Button nel suo uso normale prevede soltanto una stringa da visualizzare, per cui il contenitore classico dovrebbe prevedere un controllo Label/TextBlock che la visualizzi.

Se il programmatore ha bisogno di inserire anche un'immagine (o soltanto un'immagine), può benissimo sostituire il contenitore standard con uno ad hoc allo scopo.

Al giorno d'oggi ci sono moltissime applicazioni che hanno icone/immagini all'interno dei pulsanti, anche nel settore mobile i pulsanti principali, oltre ad avere un testo, sono spesso accompagnati da un'immagine esplicativa per cui in questo modo semplificherei molto il lavoro di colui che dovrà inserire un'eventuale immagine, pensa solo alla noia di dover allineare a mano l'immagine in base al testo... cmq prima di considerare definitivo il lavoro farò dei benchmarks e se la gestione di eventuali immagini "consuma troppo" la toglierò.
Il sistema per come è progettato non si dovrebbe appesantire specialmente se il programmatore sceglie di utilizzare la cache (switchabile per ogni singolo gadget), in questo caso, in fase di creazione, il gadget viene renderizzato in un brush e successivamente il rendering sarà solo del brush, quindi non ha molta importanza quanti elementi ci sono stati inseriti ma l'impatto lo da solo la dimensione del brush che rappresenta il gadget (comprensivo di eventuali trasparenze della skin).
In caso di modifica o resize invece la cache degli oggetti interessati sarà ricostruita e in quel momento potrei avere qualche piccola perdita di performance...

Inoltre non utilizzo un controllo label all'interno del pulsante ma quattro che rappresentano i singoli stati del pulsante in modo da avere il massimo della personalizzazione e una semplificazione delle routine di rendering/caching.



...dopo alcuni minuti...  :)
Stavo riflettendo sulla possibiltà di rappresentare il <button> con una classe label e una image proprio come elementi child, questo però non è possibile perchè nel caso volessi renderizzare il testo sopra l'immagine il sistema di layout non me lo permetterebbe perchè può solo gestire elementi con allineamento verticale e orizzontale (forse in futuro anche a griglia), ma non sovrapposti... esiste in altri sistemi questa possibilità?
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 21 Agosto 2011, 11:41:57
Coi Button di WPF/Silverlight ho totale controllo su quello che dev'essere visualizzato.

Questo significa che l'unico child può essere costituto da:
- uno stack panel con elementi allineati tutti in verticale oppure orizzontale;
- una grid in cui definisco quante righe e/o quante colonne, con relativi allineamenti e vincoli sulle dimensioni (es: i primi 2 controlli e l'ultimo hanno dimensione automatica, mentre il terzo prende tutto lo spazio che può);
- un canvas in cui specificare in maniera precisa dove piazzare i singoli componenti.

Questo solo per fare qualche esempio.

Io non ho problemi di allineamento verticale oppure orizzontale, perché il Button calcola automaticamente la sua dimensione in base ai child che contiene (e i vincoli imposti); è poi la sua area totale a subire, a sua volta, i vincoli definiti per se stesso in base agli altri controlli con cui deve "relazionarsi".

Quindi posso definire se l'area del Button ha allineamento orizzontale e verticali coi rispettivi vincoli (a sinistra, destra, centro, o "stretchato" per riempire lo spazio a disposizione; alto, basso, centrato o stretchato). E ci sono vincoli analoghi per definire l'allineamento del child nell'area a disposizione del Button.

Per fare un esempio pratico, se devo avere un bottone con etichetta + immagine, il suo child lo posso impostare come segue:
Codice: [Seleziona]
<StackPanel Orientantion=Horizontal>
    <TextBlock Text="Questa è una prova" />
    <Image Source="Images/TrashIcon.png" />
</StackPanel>
Label a destra, immagine a sinistra; stesso spazio occupato da entrambi.

Codice: [Seleziona]
<StackPanel>
    <Image Source="Images/TrashIcon.png" />
    <TextBlock Text="Questa è una prova" />
</StackPanel>
Immagine in alto, label in basso (l'orientamento di default degli StackPanel è verticale); stesso spazio occupato da entrambi.

Codice: [Seleziona]
<Grid>
   <Grid.ColumnsDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
   </Grid.ColumnsDefinitions>
    <Image Grid.Column="0" Source="Images/TrashIcon.png" />
    <TextBlock Grid.Column="1" Text="Questa è una prova" />
</Grid>
Immagine a sinistra, etichetta a destra; l'immagine occupa lo spazio strettamente necessario, mentre il testo tutto lo spazio che può.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Agosto 2011, 12:26:25
Ok, quindi a parte il fatto che non ho ancora un supporto XML/XAML e un orientamento Grid direi che ci siamo, infatti il tuo stesso esempio posso realizzarlo con:

Codice: [Seleziona]
GroupGad = HGui.Gadget:new(#HGUI_GROUP_GADGET, { caption = { "GROUP" }, window = mywin })
LabelGad = HGui.Gadget:new(#HGUI_LABEL_GADGET, { caption = { "Label gadget" }, window = mywin })
ImageGad = HGui.Gadget:new(#HGUI_IMAGE_GADGET, { image = "test.png" }, window = mywin })

GroupGad:setlayout({ gadgets = { LabelGad, ImageGad }} )
[*]
I layout possono essere nidificati fino a che c'è spazio per visualizzarli.

Ho omesso una miriade di opzioni quali "i pesi" dei due gadget all'interno del gruppo, l'allineamento (vericale di default), i bordi e altri parametri di tuning. Così come ho scritto i due gadget saranno ridimensionabili in base al contenitore con dimensioni equamente ripartite.

Un esempio di definizione di un pulsante con icona uguale su tutti e quattro gli stati potrebbe essere:
Codice: [Seleziona]
myButton = HGui.Gadget:new(#HGUI_BUTTON_GADGET,
                           { look = { icons = { iname = "Test_Icon",
                                                alignment = #HGUI_ALIGN_LEFT + #HGUI_ALIGN_VCENTER }},
                             caption = { "BUTTON", "YEAH!" },
                             actions = { onpushed = EventTester },
                             window = mywin3 })
In questo modo, di default, avrò l'icona posizionata a sinistra e centrata verticalmente nel pulsante, mentre il testo sarà centrato orizzontalmente nello spazio rimanente e verticalmente nel pulsante.
Tuttavia se avessi specificato il tag seguente nello stesso scope di <icons>:
Codice: [Seleziona]
AdjText = False
Il testo sarebbe stato centrato orizzontalmente senza tenere conto dell'icona e quindi con la possibilità di sovrascriverla che in alcuni casi potrebbe venire utile, tipo (mockup):
(http://http://img808.imageshack.us/img808/6264/stoppb.jpg)
Questa visualizzazione utilizzando due child non è possibile




[*]
Avrei potuto anche nidificare la costruzione degli oggetti direttamente nella definizione del layout:
Codice: [Seleziona]
GroupGad = HGui.Gadget:new(#HGUI_GROUP_GADGET, { caption = { "GROUP" }, window = mywin })

GroupGad:setlayout({ gadgets = { HGui.Gadget:new(#HGUI_LABEL_GADGET, { caption = { "Label gadget" }, window = mywin }),
                                 HGui.Gadget:new(#HGUI_IMAGE_GADGET, { image = "test.png" }, window = mywin }) }} )

Ma così è meno leggibile e più incasinato in caso di modifiche del codice...

EDIT: corretto un errore di digitazione
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 21 Agosto 2011, 12:32:43
OK, è molto flessibile anche questo sistema.

Riguardo alla sovrapposizione di più controlli, in WPF/Silverlight si può fare con la Grid se non si definiscono righe e/o colonne, oppure col Canvas, che permette di piazzare arbitrariamente i controlli dove si vuole.

Adesso ti manca, appunto, qualcosa come XAML (il massimo sarebbe XAML stesso, se fosse possibile, in modo da riciclare paro paro gli editor di GUI di casa Microsoft, che sono spettacolari), che nonostante sia XML come vedi è semplicissimo da utilizzare per definire la struttura della GUI senza ricorrere al codice.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Agosto 2011, 12:42:07
Appena avrò implemento tutti i controlli base passerò a XAML sicuramente :)
Grazie per ora per tutte le dritte e a risentirci al prossimo dubbio  :lol:
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 08 Novembre 2011, 12:17:52
Riesumo questo thread per sottoporvi una soluzione possibile che vorrei implementare per reallizare una sorta di connessione fra i vari elementi delle GUI.

Allora, ho appena implementato la classe <Switch> nella mia libreria e stavo pensando a come implementare la prossima classe che serve ad ottenere gruppi di elementi <Options> e <Radio> buttons.
Alla fine questi gruppi non sono altro che insiemi di <Switch> dove nel primo caso, <Options>, possono essere selezionati elementi multipli, mentre nel secondo caso, <Radio> una selezione esclude tutte le altre.

Al fine di rendere l'implementazione più semplice, ma anche più flessibile, ho pensato di non implementare una classe apposita ma bensì di lasciare al programmatore la facoltà di creare questi gruppi si switch liberamente all'interno della propria GUI e successivamente implementare una funzione che raggruppi questi elementi così che l'engine sia in grado di riconscere questi gruppi per gestirli correttamente.

Esempio, supponiamo che voglia creare una GUI del genere:
Codice: [Seleziona]
--- layout GUI ---
[SwitchA][RadioA ]
[SwitchB][RadioB ]
[SwitchC][SwitchD]
         [RadioC ]
Tutti gli elementi sono <Switch>, ma ho bisogno di identificare il gruppo che racchiude tutti i Radio per poterli gestire correttamente, quindi avevo pensato ad una funzione che possa fare questa operazione:
Codice: [Seleziona]
HGui.Links:new(link_type, data)
In questo esempio specifico sarebbe:
Codice: [Seleziona]
HGui.Links:new(#HGUI_LINKTYPE_RADIO, { objects = { RadioA, RadioB, RadioC }})
Questa funzione creerebbe un oggetto <Link> che mi tiene traccia del collegamento fra gli switch e memorizzerebbe il puntatore a tale oggetto in un campo <Links> di ogni oggetto coivolto.
In questo modo quando ho un'interazione con l'oggetto posso immediatamente verificare nel suo campo link se ci sono connessioni o raggruppamenti e gestire con estrema semplicità la sua funzione.
Ovviamente ogni oggetto potrà avere più link e quindi uno stesso Radio ad esempio potrebbe far parte di due o più gruppi permettendo dinamiche semplici da realizzare per gui complesse.

Questa stessa funzione avrei intenzione di utilizzarla anche per creare link fra oggetti di tipo diverso, per esempio potrei collegare una ListView ad una Label o una StringBox per fare in modo che una volta selezionato un elemento della lista view l'oggetto collegato venga automaticamente aggiornato senza alcun codice supplementare.

Spero di essermi spiegato bene perchè stamattina l'elettricità che c'è nell'aria mi sta fulminando quei quattro neuroni che ho nella capoccia :)

Più che altro vorrei sapere se secondo voi un'implementazione del genere potrebbe essere buona cosa oppure se implementare una classe "Options" o "Radio" sarebbe meglio (anche se secondo me molto più limitante).
 :ugeek:
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 08 Novembre 2011, 12:27:00
In questi casi è meglio una classe "container" / panel che raggruppi, appunto, un certo insieme di elementi.

Tutti gli elementi alla fine hanno sempre un "parent", e tramite questa relazione è possibile discriminare se sono figli dello stesso padre :D , per cui nel caso dei RadioButton si può sapere quali sono gli altri "fratelli" e agire di conseguenza quando ne viene selezionato uno (deselezionando quello precedente, eventualmente).

Non ho capito, invece, l'utilità di poter aver un oggetto collegato a più gruppi.

Per collegare oggetti diversi in modo da automatizzare alcune operazioni, potresti implementare il modello dei binding di Silverlight/WPF, di cui ti ho parlato prima.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 08 Novembre 2011, 17:21:11
Citazione
In questi casi è meglio una classe "container" / panel che raggruppi, appunto, un certo insieme di elementi.
In effetti sono partito proprio con questa idea che è quella più naturale poi però ho pensato alla possibilità di gestire insiemi di opzioni con elementi non compatibili e da li ho partorito questa idea, supponi di voler rappresentare due insiemi di opzioni con alcuni elementi non compatibili fra loro:

A, B, C, D possono avere una selezione multipla
E, F sono incompatibili con A, B, C, D, ma compatibili fra loro quindi se li seleziono qualsiasi opzione incompatibile dev'essere disattivata
Come li rappresenti con una GUI classica?

Col mio sistema dovrei definire un container che contenga le opzioni A, B, C, D, E, F (solo per fini estetici per il layout).
Poi con la funzione supposta farei:
Codice: [Seleziona]
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { A, E } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { B, E } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { C, E } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { D, E } })

HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { A, F } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { B, F } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { C, F } })
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { D, F } })

Se invece dovessi implementare il classico gadget dei RADIO basterebbe una sola riga:
Codice: [Seleziona]
HGui.Link:new(#HGUI_LINKTYPE_RADIO, { Objects = { A, B, C, D, E, F } })
Citazione
Tutti gli elementi alla fine hanno sempre un "parent", e tramite questa relazione è possibile discriminare se sono figli dello stesso padre :D , per cui nel caso dei RadioButton si può sapere quali sono gli altri "fratelli" e agire di conseguenza quando ne viene selezionato uno (deselezionando quello precedente, eventualmente).
Si, questo è chiaro, ma in questo specifico caso le opzioni sono trattate come entità singole, ma se il programmatore vuole le "infila" in un cantainer (classe Group) e se li ritrova tutti nel campo Childs del contenitore.

Citazione
Non ho capito, invece, l'utilità di poter aver un oggetto collegato a più gruppi.
Come vedi nell'esempio che ho fatto gli oggetti switch sono collegati fra loro da molteplici relazioni (2 per A, 2 per B, ... 4 per E e 4 per F), oltre a questo caso, con questa implementazione, sarebbe molto semplice collegare gli oggetti fra loro per degli aggiornamenti automatici, metti che ho una ListView e che il suo elemento corrente vorrei che fosse rappresentato nello Switch A, dovrei solo aggiungere nel codice questa riga (sto ancora teorizzando :) ):
Codice: [Seleziona]
HGui.Link:new(#HGUI_LINKTYPE_CAPTION, { Source = MyListViewObject, Destination = A })

Non lo so se sto prendendo una cantonata, ma questa implementazione mi sembrerebbe decisamente più flessibile di una classe separata apposita per questo tipo di gadget, senza contare poi il discorso di collegamente multipli fra oggetti e delle automazioni sugli aggiornamenti dei gadget senza ustilizzare codice aggiuntivo da parte del programmatore (e quindi risparmio di tempo).
E' ancora tutto a livello teorico, non ho scritto una sola riga di codice perchè, appunto, volevo qualche parere :)


...mumble mumble...
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 08 Novembre 2011, 17:50:54
Per questo ci sono i binding, come dicevo prima, che mettono a disposizione una enorme flessibilità.

Ti faccio un esempio con XAML (per Silverlight):
Codice: [Seleziona]
<TextBlock Text="{Binding ElementName=MyTimeout, Path=Value, Converter={StaticResource HoursFormatter}}"/>
<Slider Name="MyTimeout" Minimum="1" Maximum="24" SmallChange="1" Value="1"/>
Il controllo TextBlock ha "legato" la sua proprietà Text (di tipo stringa) alla proprietà Value (di tipo double) dell'oggetto UI che si chiama MyTimeout (lo slider definito subito dopo).

In questo modo non appena MyTimeout.Value cambia, il nuovo valore viene inviato alla proprietà Text del primo controllo.

La cosa interessante di quest'esempio è che il binding fa uso di un "convertitore". In .NET si tratta di una classe che ha la funzione di effettuare una conversione, appunto, di un valore che gli viene passato (il double dello Slider). Nello specifico, il controllo TextBlock visualizza qualcosa del tipo "1 ore", "2 ore", ..., "24 ore" proprio grazie al converter.

Un'altra cosa utilissima dei binding è che possono essere bidirezionali: se cambia il valore dello Slider, cambia anche quello del TextBlock (o TextBox nel caso in cui si voglia un edit text in cui l'utente immette del testo).

Questo funziona anche con le property di una classe. Esempio:
Codice: [Seleziona]
<Slider Minimum="1" Maximum="24" SmallChange="1" Value="{Binding MiaIstanza, Path=Valore, Mode=TwoWay}"/>Supponendo che MiaIstanza sia l'istanza di una classe che espone la property pubblica Valore, effettuandone il binding bidirezionale con la property Value dello Slider si verificherà, appunto, che qualunque cambiamento alle due property si rifletterà anche sull'altra.

Tornando al problema dei RadioButton, personalmente non complicherei l'implementazione del framework per tenere conto di questi casi che non sono molto diffusi. In questi casi risolvo tutto da codice: piazzo un delegate negli eventi Checked e Unchecked di tutti i controlli RadioButton, e risolvo manualmente i casi di incompatibilità.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 08 Novembre 2011, 17:59:25
Citazione da: "cdimauro"
Tornando al problema dei RadioButton, personalmente non complicherei l'implementazione del framework per tenere conto di questi casi che non sono molto diffusi. In questi casi risolvo tutto da codice: piazzo un delegate negli eventi Checked e Unchecked di tutti i controlli RadioButton, e risolvo manualmente i casi di incompatibilità.

Yes! anche perchè le regole di controllo di coerenza potrebbero essere note soltanto a runtime (ad esempio a seguito di un'interrogazione ad un DB, oppure in base al verificarsi di specifiche condizioni). Un UI toolkit non dovrebbe consentire eccessivo controllo sulle policies, ma fornire soltanto le meccaniche.

Il Binding tra due proprietà, seppur comodo, viola parzialmente la separazione tra View e Model. Questo può essere accettabile in molti casi, ma offrendo al programmatore un sistema "troppo potente" per costruire una GUI si rischia di invogliare la produzione di spaghetti-code :-)

Per questo motivo non andrei oltre il basilare data-binding.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 08 Novembre 2011, 18:14:08
Infatti non a caso Microsoft parla di pattern (o modello) Model View ViewModel, che è diverso dal classico MVC.

Comunque questo tipo di binding avanzato ha indubbi vantaggi, anche se effettivamente lega troppo model e view. Però uno dei vantaggi è che risulta anche semplice testare la GUI, costruendo degli appositi mock. Cosa che non ho potuto sperimentare finora causa cronica mancanza di tempo.

Personalmente ho utilizzato per lo più il databinding nei miei progetti. Con WPF si può fare anche meglio (rispetto a Silverlight) per cercare di evitare legare troppo model e view, perché è possibile definire dei trigger che scattano al verificarsi di determinate condizioni, riducendo molto il "code behind".
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 08 Novembre 2011, 21:19:06
Ok, credo di aver capito il punto...
perciò implementerò una classe dedicata al gruppo di opzioni, ma secondo voi l'implementazione dei Link fra oggetti è adeguata per il successivo supporto del binding con XAML? Se così fosse dovrei solo prevedere il supporto per i convertitori (me ne ero totalmente dimenticato :P).

Bello questo forum  :mrgreen:
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: cdimauro - 08 Novembre 2011, 21:57:23
Francamente non ho pensato alla possibile implementazione. So per certo che il binding altro non è che una classe in .NET, ma non so come funzioni tutto il meccanismo.

Dovrei pensarci un po', ma ho bisogno di un po' di tempo: al momento ho parecchie rogne da sistemare.
Titolo: Re: Interfacce e comportamento pulsanti
Inserito da: Allanon - 08 Novembre 2011, 22:00:54
Non ci sono problemi, fai con calma tanto prima che arrivo all'implementazione di queste cose devo terminare tutte le classi mancanti perciò ce ne ho di codice da macinare  :D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Marzo 2015, 22:55:43
Dopo oltre 4 anni di sviluppo sono quasi pronto per una prima release del mio framework per Hollywood chiamato HGui.
Si tratta di una libreria per creare GUI che non dipendono da nessun sistema ospite ne da librerie esterne quindi funzioneranno e saranno visualizzate su ogni sistema esattamente come sono state progettate dallo sviluppatore.

Mi farebbe piacere, per chi ne avesse voglia e tempo, di dare un'occhiata alla demo che ho rilasciato e che potete scaricare da questo link dropbox:
https://www.dropbox.com/sh/lt2cb5coa9kufzn/AACRYLwl06SSTKqM5QaB0AGta?dl=0

Ci sono tutte le versioni supportate da Hollywood, oltre all'eseguibile che vi interessa dovrete scaricare anche la cartella <HGui_ShowCaseResources> che contiene alcune immagini usate dalla demo. Le versioni MacOS non necessitano di questa cartella perchè è già inclusa nella cartella dell'app.

Se siete curiosi e volete più info qua c'è il thread che ho aperto sul forum di Hollywood -> Click (http://forums.hollywood-mal.com/viewtopic.php?f=7&t=1032).

Immagini:
(http://i60.tinypic.com/2qbduyv.png)
(http://i59.tinypic.com/35b8axy.png)

Sono graditi feedback e comportamenti anomali  ;D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 21 Marzo 2015, 22:58:43
Ma complimenti! :D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 21 Marzo 2015, 23:01:51
Grazie!
E' stata un'avventura a dir poco epica... speriamo non ci siano bachi subdoli, c'è ancora qualcosina da fixare, ma robetta di poco conto  :D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: schiumacal - 23 Marzo 2015, 10:54:22
Veramente bravo  :)

Io avevo gia' a suo tempo scaricato e ordinato per benino le tue Scuilib che ritengo siano molto utili per diverse applicazione sviluppate con Hollywood.

Ora con HGui e' ancora meglio.

Tienimi aggiornato  :)
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 23 Marzo 2015, 11:11:22
Certo :-)
Continuerò a postare su questo thread  :D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: paolone - 25 Marzo 2015, 14:27:21
...però se...

1. Premo il LMB su un pulsante e mantengo premuto -> windows disegna il pulsante premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante normale
3. Lascio il LMB, e poi lo ripremo in un'area non attiva
4. sempre mantenendo il LMB premuto entro sul pulsante del punto 1 -> windows mi disegna il pulsante evidenziato
5. Lascio il LMB -> windows lancia l'evento
A me questo comportamento non sembra proprio corretto, primo percè ho lasciato il LMB fuori dal pulsante e poi perchè mi lancia l'evento su un rilascio del LMB in seguito ad un evento di evidenziazione e non di pressione...

Ditemi voi, forse sono io che prendo un abbaglio ma se devo riprodurre questi comportamenti è bene che sappia precisamente cosa è giusto e cosa no  <!-- s:D -->:D<!-- s:D -->

Sei tu che stai prendendo un abbaglio. Stai semplicemente unendo fra di loro due eventi separati, aspettandoti un comportamento diverso da quello che avevi già descritto in precedenza (nella parte che ho tagliato), dovuto soltanto al fatto che sei uscito e poi rientrato sullo stesso pulsante.

Modifichiamo un secondo il tuo ragionamento, ipotizzando invece che tu abbia selezionato in due tempi, due pulsanti diversi:

1. Premo il LMB su un pulsante A e mantengo premuto -> windows disegna il pulsante A premuto
2. Esco dall'area sempre son il LMB premuto -> windows disegna il pulsante A normale
3. Lascio il LMB, e poi lo ripremo in un'area non attiva
4. sempre mantenendo il LMB premuto entro sul pulsante B -> windows mi disegna il pulsante evidenziato
5. Lascio il LMB -> windows lancia l'evento "B"

Nel tuo caso, semplicemente B == A. Hai fatto due cose diverse, non una sola. Ora, dubito che Windows tenga un registro di tutti gli eventi a cui l'utente ha rinunciato (cliccare, tenere premuto e uscire dall'area del pulsante = rinunciare a premerlo), per tanto l'unica azione effettivamente compiuta nel tuo esempio è quella che hai riportato nei punti 4 e 5.
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: paolone - 25 Marzo 2015, 14:31:57
@Allanon

Intanto ne approfitto anch'io per farti i complimenti. Spero che HGui ti permetta almeno di rientrare nell'investimento di tempo, fatica e stress che sicuramente hai dovuto affrontare per realizzarlo.
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 25 Marzo 2015, 17:22:11
Mi sembra che poi venne fuori che questo comportamento lo avevo solo con PSPad :)

Cmq grazie per i complimenti, non ho la pretesa di riprenderci il tempo investito ma di recuperarci un paio di aggiornamenti ad Hollywood  :D
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 15 Giugno 2015, 16:20:55
Ancora ci sto lavorando... la classe ListView è infinita  ;D

Comunque l'ultimo problema che ho risolto riguarda la manipolazione dei valori in visualizzazione: mi spiego meglio.

Supponiamo che ho una tabella con due colonne: nomi file e dimensione file (in bytes) e voglia mostrarla in una ListView.
Tutto ok, nessun problema, però le dimensioni in byte fanno pena e voglio mostrarle in Kb come faccio?

La prima cosa che viene in mente è convertire i dati e passarli alla ListView, quindi ogni dimensione in byte la converto in Kb e aggiungo il suffisso "Kb", il valore da numerico passa inevitabilmente a stringa.

Bene, i dati sono visualizzati ma se premo il pulsante dell'intestazione della colonna per cambiare ordinamento tutto va a farsi fottere perchè adesso sono stringhe e l'ordinamento delle stringhe prevede, per esempio, che "45Kb" venga prima di "4Kb"  :)

Per risolvere questa zozzeria ho aggiunto la possibilità di definire dei convertitori associati alle colonne delle ListView, ossia delle funzioni che vengono invocate ogni volta che un valore di una determinata colonna deve essere visualizzato. Queste funzioni possono essere cambiate al volo e si prestano anche a dei giochetti carini per evidenziare le colonne o manipolare i dati in visualizzazione.

Quindi, ricapitolando, adesso passo i valori in byte e specifico questa funzione per la colonna delle dimensioni:
Codice: [Seleziona]
function(value) return((value/1024) .. "Kb") endfunction

E tutti vissero felici e contenti :)

P.S.: tra l'altro in questo modo non ho la necessità di inzozzare i dati originali per visualizzarli.
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 15 Giugno 2015, 18:54:59
Ottima soluzione :)
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 15 Giugno 2015, 19:46:02
Grazie :)
Quando ho iniziato questo progetto neanche mi passava per la testa che avrei incontrato certe problematiche   :P
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Z80Fan - 15 Giugno 2015, 20:41:39
Concordo, è un metodo molto comodo e semplice applicabile a molte situazioni. :)
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: Allanon - 16 Giugno 2015, 11:55:46
Quasi quasi pensavo di espandere questa implementazione anche agli altri campi (label, text, ecc...), secondo voi ha senso? O ci dovrebbe pensare ci creerà le gui?

L'overhead non è significativo perchè durante la creazione, come ho fatto nel ListView, se non viene specificata la funzione di conversione di default imposto

Codice: [Seleziona]
function(v) return(v) endfunction

che mi elimina il controllo
Codice: [Seleziona]
la funzione di conversione è specificata?
   si -> usala per convertire il dato
   no -> restituisci il dato così com'è
Titolo: Re:Interfacce e comportamento pulsanti
Inserito da: TheKaneB - 16 Giugno 2015, 12:34:36
mah, direi che non dovrebbe cambiare praticamente nulla.
Forse se metti il controllo IF semanticamente ha più senso, ma a livello di funzionalità sono equivalenti.