Notte fonda e mi chiedevo perchè indexOff mi da sempre -1 ?
B4X:
Public Sub mMenu_add(mMenuBar As MenuBar,menu As MenuItem)
If mMenuBar.Menus.IndexOf("Resume") = -1 Then
Dim mMenu As Menu
mMenu.Initialize("Resume","")
mMenuBar.Menus.Add(mMenu)
mMenu.MenuItems.Add(menu)
Else
Dim mMenu As Menu = mMenuBar.Menus.Get(mMenuBar.Menus.IndexOf("Resume"))
mMenu.MenuItems.Add(menu)
End If
End Sub
In effetti è un po' ingeneroso; almeno la sufficienza potrebbe dartela ?
Su cosa esegui la funzione IndexOf? Su una List; ma di che tipo, stringa, per cui cerchi (chissà perché) "Resume"? No, è una lista di oggetti MenuItem:
Eh, te lo aggiusto... si fa per dire, in quanto la cosa non funziona come immaginavo.
Stavo scrivendo una routine in questo modo (che già in partenza non mi "piaceva" in quanto dovrebbe poter aggiungere nuovi menu non solo ad una MenuBar ma anche a dei MenuItem):
B4X:
' Qui, anziché passare un MenuBar, si dovrebbe passare un MenuItem,
' ovvero dare la possibilità di aggiungere un menu non soltanto ad un MenuBar
' ma anche ad un MenuItem, ovvero un sottomenu.
Public Sub AddMenu(Menu As MenuBar, NewMenuText As String)
Dim MenuAlreadyExists As Boolean
For Each Item As MenuItem In Menu.Menus
If Item.Text = NewMenuText Then
MenuAlreadyExists = True
Exit
End If
Next
If Not(MenuAlreadyExists) Then
' Il menu con testo NewMenuText non esiste, lo creo e lo aggiungo.
Dim NewMenuItem As MenuItem
NewMenuItem.Initialize(NewMenuText, NewMenuText)
' Menu. <--- qui avrei aggiunto NewMenuItem alla lista Menu.Menus; peccato che sia una lista in sola lettura!
End If
End Sub
Ergo, si dovrà fare in modo diverso, ancora da scovare...
Nell'immagine che ho aggiunto al mio primo post, in effetti si vede che il tipo è Menu, ma pensavo fosse un piccolo errore nella descrizione e che fosse MenuItem.
Beh, non è così. Esiste il tipo Menu, che ha una lista di MenuItem cui se ne possono aggiungere altri, mentre il tipo MenuBar ha una lista Menus che però è read-only!
Un po' un casino; anche perché non si può fare casting tra i vari tipi.
@LucaMs il problema non è che è read-only! perche devo solo vedere se esiste, se non esiste lo creo, ma non lo legge nemmeno dopo creato..
li ceo cosi al via del main
qui li imposto
B4X:
If Global.ToastMessage(mFooter,"Welcome back, I'm getting organized for work.") = True Then
Global.mMenu_menu(mMenuBar,"Actions",Array As String("Login","New user","Close"))
Global.mMenu_menu(mMenuBar,"Modules",Array As String("Organizer","Calendar"))
Global.mMenu_menu(mMenuBar,"Additional modules",Array As String(""))
Global.mMenu_menu(mMenuBar,"Resume",Array As String(""))
End If
qui li istanzio e creo
B4X:
Public Sub mMenu_menu(mMenuBar As MenuBar,title As String, Args() As String)
Dim mMenu As Menu
mMenu.Initialize(title,"")
mMenu.Tag=title
mMenuBar.Menus.Add(mMenu)
If Args(0)="" Then Return
For i=0 To Args.Length-1
Dim mi As MenuItem
mi.Initialize(Args(i),"Actions")
mMenu.MenuItems.Add(mi)
Next
End Sub
qui aggiungo poi le voci mancanti
B4X:
Public Sub mMenu_add(mMenuBar As MenuBar,menu As MenuItem)
If mMenuBar.Menus.IndexOf("Resume") = -1 Then
Dim mMenu As Menu
mMenu.Initialize("Resume","")
mMenuBar.Menus.Add(mMenu)
mMenu.MenuItems.Add(menu)
Else
Dim mMenu As Menu = mMenuBar.Menus.Get(mMenuBar.Menus.IndexOf("Resume"))
mMenu.MenuItems.Add(menu)
End If
End Sub
nulla di che, ma se poi leggo il suo contenuto con Log(mMenuBar.Menus)
"nulla di che" lo dici tu! Ripeto che quella tua routine non può funzionare (e oltretutto scritta così non ha senso, perché, se funzionasse e non può, aggiungerebbe sempre e solo un menu col testo "Resume", che hai scritto nella routine stessa:
B4X:
Public Sub mMenu_add(mMenuBar As MenuBar,menu As MenuItem)
If mMenuBar.Menus.IndexOf("Resume") = -1 Then
Dim mMenu As Menu
mMenu.Initialize("Resume","")
mMenuBar.Menus.Add(mMenu)
mMenu.MenuItems.Add(menu)
Else
Dim mMenu As Menu = mMenuBar.Menus.Get(mMenuBar.Menus.IndexOf("Resume"))
mMenu.MenuItems.Add(menu)
End If
End Sub
Tu stesso hai scritto che quella IndexOf ti restituisce sempre -1 e ti ho spiegato il motivo, perché tu gli fai cercare "Resume", che è una stringa, in una lista, Menus, che non è una lista contenente stringhe, ma oggetti di tipo Menu!
Il problema che continua ad aggiungere menu resume ad ogni record che e da resumare hahahahah
B4X:
Public Sub LoadResumeItem(idlogin As String)
If Global.SQL_Exists = False Then Return
Dim sqlite As SQL
sqlite.InitializeSQLite(File.DirApp,"data.sqlite", False)
Dim SenderFilter As Object = sqlite.ExecQueryAsync("SQL", "SELECT fullname,id FROM item where userid='" & idlogin & "' and hide='false' order by fullname",Null)
Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, rs As ResultSet)
Dim cm As ContextMenu
cm.Initialize("")
If Success Then
Dim i As Int
Do While rs.NextRow
i = i + 1
Dim it As MenuItem
it.Initialize(rs.GetString("fullname"),"resume")
Dim lsTemp As List
lsTemp.Initialize
lsTemp.Add(rs.GetString("fullname"))
lsTemp.Add(rs.GetString("id"))
lsTemp.Add(Global.idlogin)
it.Tag=lsTemp
Global.mMenu_add(mMenuBar,it)
Loop
If i = 0 Then
'nessun risultato trovato
Log($"No results found"$)
End If
rs.Close
Else
Log(LastException)
End If
End Sub
questo e solo il codice di quando seleziono la voce menu, tutto funziona perfettamente, ma crea tanti menu("Resume")
B4X:
Sub resume_Action
Dim mi As MenuItem = Sender
Dim lstemp As List = mi.Tag
Dim sqlite As SQL
sqlite.InitializeSQLite(File.DirApp,"data.sqlite", False)
Dim query As String = "UPDATE associates SET hide = 'true' WHERE idmaster='" & lstemp.Get(1) & "' OR idassociates='" & lstemp.Get(1) & "' AND userid='" & Global.idlogin & "';"
sqlite.ExecNonQuery(query)
query = "UPDATE item SET hide = 'true' WHERE id='" & lstemp.Get(1) & "'AND userid='" & Global.idlogin & "';"
sqlite.ExecNonQuery(query)
mi.Enabled=False
mClassOrganizer.loadItem
End Sub
ho risolto in altro modo ma questa e il solito cerotto, a volte si dice "Funziona!!","allora che te frega", in realtà voglio gestirlo in maniera più corretta ma non so che cosa vuol dire corretta.
@LucaMs ho cercato come stringa e come menu (oggetto) il risultato e sempre lo stesso
B4X:
Public Sub LoadResumeItem(idlogin As String)
If Global.SQL_Exists = False Then Return
Dim sqlite As SQL
sqlite.InitializeSQLite(File.DirApp,"data.sqlite", False)
Dim SenderFilter As Object = sqlite.ExecQueryAsync("SQL", "SELECT fullname,id FROM item where userid='" & idlogin & "' and hide='false' order by fullname",Null)
Wait For (SenderFilter) SQL_QueryComplete (Success As Boolean, rs As ResultSet)
Dim cm As ContextMenu
cm.Initialize("")
Dim lsMenuItem As List
lsMenuItem.Initialize
If Success Then
Dim i As Int
Do While rs.NextRow
i = i + 1
Dim it As MenuItem
it.Initialize(rs.GetString("fullname"),"resume")
Dim lsTemp As List
lsTemp.Initialize
lsTemp.Add(rs.GetString("fullname"))
lsTemp.Add(rs.GetString("id"))
lsTemp.Add(Global.idlogin)
it.Tag=lsTemp
lsMenuItem.Add(it)
Loop
If i = 0 Then
'nessun risultato trovato
Log($"No results found"$)
End If
rs.Close
Else
Log(LastException)
End If
Global.mMenu_Resume(mMenuBar,"Resume",lsMenuItem)
End Sub
B4X:
Public Sub mMenu_Resume(mMenuBar As MenuBar, title As String, lsMenuItem As List)
Dim mMenu As Menu
mMenu.Initialize(title,"")
mMenu.Tag=title
mMenuBar.Menus.Add(mMenu)
mMenu.MenuItems.AddAll(lsMenuItem)
End Sub
In realtà, quando devo risolvere un problemino, poi mi metto a sviluppare qualcosa che possa essere riutilizzato e che si il più generico ed ampio possibile.
Ecco perché avevo scritto:
In effetti, una classe (o modulo) che servisse a gestire una MenuBar, con possibilità di aggiungere, rimuovere, abilitare/disabilitare, salvare, etc. potrebbe essere utile.
Per il momento "mi accontento" di darti una mano.
Ti serve poter aggiungere "singole voci di menu" (ovvero senza sottomenu di queste) ad uno dei menu già presenti nella MenuBar1?
Questo lo capirei, per la voce del MenuBar1 "Additional modules" e sarebbe semplice.
Anche volendo fare la stessa cosa per il menu "Resume" (*).
Se invece vuoi poter aggiungere runtime qualunque "tipo" di menu, a qualunque livello, la cosa è più complicata e servirebbe appunto una classe (o modulo di codice) come detto all'inizio.
Che poi, tra l'altro, tutti i menu, compresi quelli della menu bar principale (unica, direi) andrebbero creati a runtime, per un semplice motivo: poter "localizzare" il sw, ovvero poter scrivere le voci in varie lingue.
@LucaMs i menu sono creati tutti a Runtime (guarda il codice) il menubar e di layout (che è vuoto) e a codice creo i menu dinamici con i sottomenu
MenuBar > Menus > MenuItem
Pare ovvio che quando creo iMenuItemper ilMenu "Resume" lo faccio dopo il login (caricare i dati a secondo il login che mi restituisce idlogin (member), quindi mediante la query richiamo ii record che sono in stato hide (nascosti) e quindi non visibili, in questo modo avendo il menu posso resumarli (facciamo una croce) hahahah che è diveso dal elimina, che li elimina in modo permanente.
Resume: lista di record messi nascosti con un hide=false
Non vorrei complicarvi la vita, ma i Menu posti direttamente sulla MenuBar sono in numero predefinito (o hanno un max predefinito calcolato sulla lunghezza media della label e lo spazio disponibile)? In caso contrario, la MenuBar è (o si appoggia su) una horizontal scroll view di qualche genere?
Non vorrei complicarvi la vita, ma i Menu posti direttamente sulla MenuBar sono in numero predefinito (o hanno un max predefinito calcolato sulla lunghezza media della label e lo spazio disponibile)? In caso contrario, la MenuBar è (o si appoggia su) una horizontal scroll view di qualche genere?
Non vorrei complicarvi la vita, ma i Menu posti direttamente sulla MenuBar sono in numero predefinito (o hanno un max predefinito calcolato sulla lunghezza media della label e lo spazio disponibile)? In caso contrario, la MenuBar è (o si appoggia su) una horizontal scroll view di qualche genere?
Cmq, anche se io ed Ivano parliamo due lingue diverse ?, suppongo che lui voglia aggiungere sotto-menu a runtime, non menu della MenuBar.
Il che non significa che non si debba impostare un limite anche per questi, comunque!
Dagli esempi mi sembrava che gli interessassero entrambe le possibilità.
In Android cè il menu di overflow (i tre puntini impilati che si vedevano sulla destra), ma non è che mi faccia impazzire. Uno scrolling orizzontale (XCLV o HSV) credo sia migliore, ma bisogna ricordarsi di segnalare graficamente la presenza di altre voci e poi "sincronizzare" la posizione del sub-menu con il menu selezionato.
Sempre che, come dicevi, il numero di Menu principali non sia limitato e calcolato in modo che rientri pienamente della MenuBar.
dovrebbe essere semplice in quanto i menu sono object, quindi si dovrebbero rintracciare con un get(i) is menu .... ma non è così come lo è per tutto il resto degli object, poi con calma trovo la soluzione corretta invece del cerotto