New UI Feature Request - Alphabet Sidebar

Post a reply

Smilies
:D :) :( :o :-? 8) :lol: :x :P :oops: :cry: :evil: :roll: :wink:

BBCode is ON
[img] is ON
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: New UI Feature Request - Alphabet Sidebar

Re: New UI Feature Request - Alphabet Sidebar

by Dreadlau » Fri Jan 07, 2011 2:23 am

Ah that looks useful. Would be nice if it was vertical too.

Oh and welcome to the forum memy. :]

Re: New UI Feature Request - Alphabet Sidebar

by memy » Thu Jan 06, 2011 11:36 pm

For this is my 1st post here - i'd like to say hello from Berlin
and thanks to all the active people here, because I already found a lot of help here.

I would like to second that.
Is there any alternative to this nice script? Or is there a way to get it working with V3.x?

memy

Re: New UI Feature Request - Alphabet Sidebar

by DocWeini » Wed Jun 17, 2009 6:00 am

I would be interested in that feature, too.
:D

Re: New UI Feature Request - Alphabet Sidebar

by DWMD65 » Wed Nov 19, 2008 12:07 am

Is there a version of this script for version 3 and if so, is there an installer?

Thanks

by Sietsy » Fri Dec 07, 2007 3:00 pm

I'm trying to make this script work on MM3, but it's not working properly. It won't work with my magicnodes 1.4 and with the 'Album Artist' node.

Does anyone know a solution?

by trixmoto » Mon May 01, 2006 7:32 am

Nice script, I like where this is heading. Personally I'd prefer a vertical bar going down the left side of the tree, but I know this currrently isn't possible.

by Steegy » Sat Apr 29, 2006 5:52 pm

Oops, sorry about that. I forgot to copy the methods to the script.
I'll upload a modified version right away.

EDIT: Show/Hide menu item is now added.

ADDITIONS:
Begges Simple Lyrics Viewer seems to have a nice implementation like that.
"Dockable ML Panel" (Embedded MiniLyrics) implementation is even better :lol:
BTW, this seems work good except when you don't have a 'library subnode' selected (ie album/artist/genre/etc).
That's by design. Changes can be made of course.
I'd prefer to wait some time, to wait for other reactions. Is that OK?
I also wonder if a vertical arrangement might be more space conservative
Indeed, that was the plan, but that's not possible yet.
A toolbar can be partially put along the library view, but in most cases it wouldn't be long enough to fit all buttons (and it would be very "uncustomisable").
A panel (best way) can only be docked above or below the tree view.
I will request better docking support (support all possible docking positions). That will be a solution for this. I already asked for an option to hide the panel's title bar.
I do think that AllMusic's interface is the nicest, but this is, as already said, not yet possible.

Concerning the "maximised" window mode: I have no problems with it, I just tested it. Maybe you can identify the problem better, and if necessary say what's wrong or post a bug report.


Cheers
Steegy

by Teknojnky » Sat Apr 29, 2006 5:52 pm

Steegy wrote:BTW: I didn't bother to add a show/hide button for the panel yet. That means that if you closed the panel, you will have to restart MediaMonkey to get it back. In a later phase, this can (and probably will) easily be added (as button on the "library shortcuts/navigation bar"). Just to avoid questions about this...
Not that this should be really necessary of course.
Might I suggest putting it into the "view" main menu, where you can show/hide the other main panels. Begges Simple Lyrics Viewer seems to have a nice implementation like that.

BTW, this seems work good except when you don't have a 'library subnode' selected (ie album/artist/genre/etc).

It would be convenient if it were usable from the 'now playing' window, or anywhere really. I would guess that having a user selectable 'default go to node' would be appropriate. (ie start with 'artist' node if no appropriate node is currently selected)

I also wonder if a vertical arrangement might be more space conservative, but I can see folks have a preference either way.

A couple pics, I don't know if this is a MM issue or can be worked around via script:

Image Maximized -> Image


MM does not seem to save states between normal and maximized window modes.

by Teknojnky » Sat Apr 29, 2006 5:17 pm

Wow Steegy, your a coding machine! Going to try it out now. Now I gotta find the utility script lol!

edit: note utility scripts are available in steegy's signature link -> resources (I didn't see it mentioned in your posts).

by Steegy » Sat Apr 29, 2006 4:55 pm

Current code (as autoscript)

Current issues:
- how should it work??
- double-clicking a button (unexpectedly) goes to the "first occurence" instead of the "next occurence"

Buttons:
%: for symbols
0: for digits 0 - 9
A - Z: for letters A - Z
<-: go to parent node
<x: go to parent node and close it

How to install scripts: http://faq.mediamonkey.com/index.php?ac ... artlang=en

Code: Select all

' Copy anything you want, but I like the credit :-)

Option Explicit
Dim SDB : Set SDB = CreateObject("SongsDB.SDBApplication")

Dim BorderlessButton : BorderlessButton = False
Dim IgnorePrefixes : IgnorePrefixes = True
Dim Prefixes : Prefixes = Array("the") ' Prefixes to ignore (the character ' is always ignored if not in the "Title" tree node)
Dim CurrentNode


Sub OnStartUp

  Call CreatePanel

End Sub


Sub CreatePanel

    Dim Panel : Set Panel = InitialisePanel
	
	Dim MI : Set MI = SDB.UI.AddMenuItem(SDB.UI.Menu_View, 1, -3)
	MI.Caption = "Library Buttons"
	MI.Checked = Panel.Common.Visible = True
	MI.Hint = "Show the library buttons panel"
	Script.RegisterEvent MI, "OnClick", "MIClick"
	Set SDB.Objects("NodeFromFirstCharacter_MenuItem") = MI
	
    
    Dim BW : BW = 16    ' button width
    Dim BH : BH = 20    ' button height


    MakeTheButton Panel, "%", BW, 0, BW, BH, "ActionSymbol"
    MakeTheButton Panel, "0", 2*BW, 0, BW, BH, "Action0"
    Dim i
    For i = 0 To 12
        MakeTheButton Panel, Chr(65 + i), 3*BW + i*BW, 0, BW, BH, "Action" & Chr(65 + i)
    Next
    For i = 13 To 25
        MakeTheButton Panel, Chr(65 + i), 3*BW + (i-13)*BW, BH, BW, 20, "Action" & Chr(65 + i)
    Next

    MakeTheButton Panel, "<-", 0, BH+3, 20, BH-3, "GotoParentNode"
    MakeTheButton Panel, "<x", 20, BH+3, 20, BH-3, "GotoParentNodeAndClose"

End Sub


Function InitialisePanel

	Set InitialisePanel = SDB.UI.NewDockablePersistentPanel("NodeFromFirstCharacter")
	If InitialisePanel.IsNew Then 
		InitialisePanel.DockedTo = 1 
		InitialisePanel.Common.Height = 100 
	End If 
	InitialisePanel.Caption = ""
	
	If SDB.IniFile.StringValue("NodeFromFirstCharacter", "PanelVisible") = "False" Then
	    InitialisePanel.Common.Visible = False
	Else
	    InitialisePanel.Common.Visible = True
	End If
	    
	Set SDB.Objects("NodeFromFirstCharacter_Panel") = InitialisePanel
	Script.RegisterEvent InitialisePanel, "OnClose", "PanelClosed"
	
End Function


Sub MIClick(MI) 

	MI.Checked = Not MI.Checked
	
	If SDB.Objects("NodeFromFirstCharacter_Panel") Is Nothing And MI.Checked Then
	    Call InitialisePanel
	End If
	
	SDB.Objects("NodeFromFirstCharacter_Panel").Common.Visible = MI.Checked
	SDB.IniFile.StringValue("NodeFromFirstCharacter", "PanelVisible") = MI.Checked

End Sub


Sub PanelClosed(Panel) 

    SDB.Objects("NodeFromFirstCharacter_MenuItem").Checked = False
    Set SDB.Objects("NodeFromFirstCharacter_Panel") = Nothing
	SDB.IniFile.StringValue("NodeFromFirstCharacter", "PanelVisible") = "False"

End Sub


Function MakeTheButton(Owner, Caption, X, Y, Width, Height, OnClickFunc)

    If BorderlessButton Then
        Call CreateBorderlessButton(Owner, Caption, X, Y, Width, Height, OnClickFunc)
    Else
        Call CreateButton(Owner, Caption, X, Y, Width, Height, OnClickFunc)
    End If

End Function


Function CreateBorderlessButton(Owner, Caption, X, Y, Width, Height, OnClickFunc)

  Set CreateBorderlessButton = SDB.UI.NewLabel(Owner)
  CreateBorderlessButton.Caption = Caption
  CreateBorderlessButton.Common.SetRect X, Y, Width, Height
  Script.RegisterEvent CreateBorderlessButton.Common, "OnClick", OnClickFunc
  
End Function


Function CreateButton(Owner, Caption, X, Y, Width, Height, OnClickFunc)

  Set CreateButton = SDB.UI.NewButton(Owner)
  CreateButton.Caption = Caption
  CreateButton.Common.SetRect X, Y, Width, Height
  Script.RegisterEvent CreateButton.Common, "OnClick", OnClickFunc

End Function


Sub ActionSymbol(Button) : NodeFromFirstCharacter "%" : End Sub
Sub Action0(Button) : NodeFromFirstCharacter "0" : End Sub

'Because dynamically created methods (using Execute or ExecuteGlobal) can't be executed from the default button event handlers, I had to implement them all at compile-time.
Sub ActionA(Button) : NodeFromFirstCharacter "A" : End Sub
Sub ActionB(Button) : NodeFromFirstCharacter "B" : End Sub
Sub ActionC(Button) : NodeFromFirstCharacter "C" : End Sub
Sub ActionD(Button) : NodeFromFirstCharacter "D" : End Sub
Sub ActionE(Button) : NodeFromFirstCharacter "E" : End Sub
Sub ActionF(Button) : NodeFromFirstCharacter "F" : End Sub
Sub ActionG(Button) : NodeFromFirstCharacter "G" : End Sub
Sub ActionH(Button) : NodeFromFirstCharacter "H" : End Sub
Sub ActionI(Button) : NodeFromFirstCharacter "I" : End Sub
Sub ActionJ(Button) : NodeFromFirstCharacter "J" : End Sub
Sub ActionK(Button) : NodeFromFirstCharacter "K" : End Sub
Sub ActionL(Button) : NodeFromFirstCharacter "L" : End Sub
Sub ActionM(Button) : NodeFromFirstCharacter "M" : End Sub
Sub ActionN(Button) : NodeFromFirstCharacter "N" : End Sub
Sub ActionO(Button) : NodeFromFirstCharacter "O" : End Sub
Sub ActionP(Button) : NodeFromFirstCharacter "P" : End Sub
Sub ActionQ(Button) : NodeFromFirstCharacter "Q" : End Sub
Sub ActionR(Button) : NodeFromFirstCharacter "R" : End Sub
Sub ActionS(Button) : NodeFromFirstCharacter "S" : End Sub
Sub ActionT(Button) : NodeFromFirstCharacter "T" : End Sub
Sub ActionU(Button) : NodeFromFirstCharacter "U" : End Sub
Sub ActionV(Button) : NodeFromFirstCharacter "V" : End Sub
Sub ActionW(Button) : NodeFromFirstCharacter "W" : End Sub
Sub ActionX(Button) : NodeFromFirstCharacter "X" : End Sub
Sub ActionY(Button) : NodeFromFirstCharacter "Y" : End Sub
Sub ActionZ(Button) : NodeFromFirstCharacter "Z" : End Sub


Sub GotoParentNodeAndClose(Button)

    On Error Resume Next
    
    Dim ParentNode : Set ParentNode = SDB.MainTree.ParentNode(SDB.MainTree.CurrentNode)
    Set SDB.MainTree.CurrentNode = ParentNode
    ParentNode.Expanded = False
    
End Sub


Sub GotoParentNode(Button)

    On Error Resume Next
    
    Dim ParentNode : Set ParentNode = SDB.MainTree.ParentNode(SDB.MainTree.CurrentNode)
    Set SDB.MainTree.CurrentNode = ParentNode
    
End Sub


Function FindNodeToStartWith(Character, IgnoreIt)
    Set FindNodeToStartWith = Nothing

    Dim PreviousNode : Set PreviousNode = SDB.Objects("PreviousFirstCharNode")
    If Not PreviousNode Is Nothing Then
        Dim FirstChar : FirstChar = GetFirstCorrectCharacter(PreviousNode.Caption, IgnoreIt)
        If IsAMatch(FirstChar, Character) Then
            If EqualNodes(PreviousNode, CurrentNode) Then
                Set FindNodeToStartWith = CurrentNode
                Exit Function
            End If
        End If
    End If
  
    Select Case SDB.MainTree.CurrentNode.NodeType
    	Case 9, 1, 2, 4: 'Title, Artist, Album, Genre main nodes
            Set FindNodeToStartWith = CurrentNode
            FindNodeToStartWith.Expanded = True
    		Set FindNodeToStartWith = SDB.MainTree.FirstChildNode(FindNodeToStartWith)
        Case 150, 60, 151, 50, 152, 52, 153, 53: 'Title, Artist, Album, Genre child nodes
            Set FindNodeToStartWith = CurrentNode
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
            FindNodeToStartWith.Expanded = True
    		Set FindNodeToStartWith = SDB.MainTree.FirstChildNode(FindNodeToStartWith)
        Case 51, 54: 'ArtistAlbum, GenreArtist nodes
            Set FindNodeToStartWith = CurrentNode
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
            FindNodeToStartWith.Expanded = True
    		Set FindNodeToStartWith = SDB.MainTree.FirstChildNode(FindNodeToStartWith)
        Case 55: 'GenreArtistAlbum nodes
            Set FindNodeToStartWith = CurrentNode
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
    		Set FindNodeToStartWith = SDB.MainTree.ParentNode(FindNodeToStartWith)
            FindNodeToStartWith.Expanded = True
    		Set FindNodeToStartWith = SDB.MainTree.FirstChildNode(FindNodeToStartWith)
    End Select

End Function



Function NodeFromFirstCharacter(Character)

'    If SDB.Objects("NodeFromFirstCharacter_Busy") Is Nothing Then
'        Set SDB.Objects("NodeFromFirstCharacter_Busy") = SDB
'    Else
'        Exit Function
'        MsgBox "2"
'    End If

    Set CurrentNode = SDB.MainTree.CurrentNode
    If CurrentNode Is Nothing Then
'        Set SDB.Objects("NodeFromFirstCharacter_Busy") = Nothing
        Exit Function
    End If
    
    Dim NodeType : NodeType = CurrentNode.NodeType
    Dim IgnoreIt : IgnoreIt = Not (NodeType = 9 Or NodeType = 150 Or NodeType = 60)
        
    Dim StartNode : Set StartNode = FindNodeToStartWith(Character, IgnoreIt)
    If StartNode Is Nothing Then
'        Set SDB.Objects("NodeFromFirstCharacter_Busy") = Nothing
        Exit Function
    End If
    
         
    On Error Resume Next

    Dim FirstChar
    
    Dim ChildNode : Set ChildNode = StartNode

    Do 
        Set ChildNode = SDB.MainTree.NextSiblingNode(ChildNode)
        
        If Err <> 0 Or (ChildNode Is Nothing) Then
'            Set SDB.Objects("NodeFromFirstCharacter_Busy") = Nothing
            Exit Function 
        End If
    
        FirstChar = GetFirstCorrectCharacter(ChildNode.Caption, IgnoreIt)
        
        If IsAMatch(FirstChar, Character) Then
            Exit Do
        End If
    Loop While True 


    Set SDB.MainTree.CurrentNode = ChildNode
    Set SDB.Objects("PreviousFirstCharNode") = ChildNode
    
'    Set SDB.Objects("NodeFromFirstCharacter_Busy") = Nothing
    
End Function


Function IsAMatch(FirstChar, Character)
    IsAMatch = False
    
    If StrComp(FirstChar, Character, 1) = 0 Then
        IsAMatch = True
    ElseIf Character = "0" Then
        If IsNumber(FirstChar) Then
            IsAMatch = True
        End If
    ElseIf Character = "%" Then
        If IsNoNumberOrLetter(FirstChar) Then
            IsAMatch = True
        End If
    End If
        
End Function


Function IsNoNumberOrLetter(InputChar)

    Dim InputCharCode : InputCharCode = Asc(InputChar)
    IsNoNumberOrLetter = (InputCharCode < 48 Or (InputCharCode > 57 And InputCharCode < 65) Or (InputCharCode > 90 And InputCharCode < 97) Or InputCharCode > 122)

End Function


Function IsNumber(InputChar)

    Dim InputCharCode : InputCharCode = Asc(InputChar)
    IsNumber = (InputCharCode > 47 And InputCharCode < 58)

End Function


Function EqualNodes(Node1, Node2)
    EqualNodes = False

    If Node1.NodeType = Node2.NodeType Then
        If Node1.Caption = Node2.Caption Then
            EqualNodes = True
        End If
    End If
  
End Function


Function GetFirstCorrectCharacter(ByVal InputText, IgnoreIt)
    Dim TextToChar : TextToChar = InputText
    
    If IgnorePrefixes Then
        TextToChar = RemovePrefix(TextToChar)
    End If
    
    If IgnoreIt And Left(TextToChar, 1) = "'" Then
      TextToChar = Mid(TextToChar, 2, 1)
    Else
      TextToChar = Left(TextToChar, 1)
    End If
    
    GetFirstCorrectCharacter = TextToChar
End Function


Function RemovePrefix(ByVal InputText)
    RemovePrefix = InputText
    
    Dim i, Prefix, PrefixLength
    For i = 0 To UBound(Prefixes)
        Prefix = Prefixes(i) & " "
        PrefixLength = Len(Prefix)
        
        If Len(InputText) > PrefixLength Then
            If StrComp(Left(InputText, PrefixLength), Prefix, 1) = 0 Then
                RemovePrefix = Mid(RemovePrefix, PrefixLength + 1)
                Exit For ' stop when a prefix has been removed
            End If
        End If
    Next

End Function
Image
The panel with the buttons has a title bar that isn't shown.

With borderless buttons (fits better on some skins, like this one):
Image

Showing/hiding the panel can be done through the "View" menu.


Borderless buttons are now possible too (yes fellow coders... how did I do that :lol: ). You can choose for borderless if you set BorderlessButton to True.

BTW: Code cleanup is on the todo list.

Cheers
Steegy

by Steegy » Sat Apr 29, 2006 4:32 pm

Code: Select all

How it currently works:
=======================

Possibility to ignore prefixes like "The" (can be enabled/disabled, prefixes can be added)
Always ignores the ' character (when not in the "Title" node) in the way that MediaMonkey does it
(as default: ignores the "The" prefix)



"first instance" = first node that matches the button pressed
"next instance" = next (sibling) node that matches the button pressed, when the previously selected node was also a match

Goes to the "first instance" child node of the selected main Title, Artist, Album or Genre node
If a such a child node is already selected, it goes to the "first instance" sibling node, unless the button was already used to go to the currently selected node (there was already a match using the button). In that case, it goes to the "next instance"
If a child node of the above mentioned child nodes is selected (the Artist>Album, Genre>Artist and Genre>Artist>Album nodes), it goes to the first instance for the above mentioned child nodes.


The script supposes:
--------------------
... that it is possible that not all entries are in alphabetical order (like when you just changed something)
- That means that the script always searches from the first possible node, until it finds a match.
- If the last matching node is reached, the script stays on the same place.

The reverse supposition would mean that the script could be made a little bit faster (if F is selected and the G button is pushed, then the script would start from the selected node instead of starting from the beginning)
Also, if the last matching node is reached, it could be made that script goes back to the first matching node.
In my opinion, that (except from "the script supposes") is the most logical thing to do.
If MediaMonkey would automaticly put edited nodes in the right place (alphabetically), I would take the "reverse supposition" immediately.

Explanation:
- Jumping from one main node to another (like Artist to Album) seems kind of confusing to me (so I'd rather have the script only work on the current node).
- Because the "child nodes of the child nodes" usually aren't very numerous (like albums from a certain artist), the script takes their parent node level to work on (the "above mentioned" child nodes).
One exception that seems logical to make is the "genre" child node, that mostly contains a large number of entries (artists).
Changing this behaviour can easily be done, if this is wanted.

Hopefully you can understand something from my unclear explanation.
Confused, I'm sorry if I made you more confused now... :wink:

The bold things are the things I will probably change...

More opinions are very welcome...

Cheers
Steegy

by Teknojnky » Sat Apr 29, 2006 10:01 am

Personally, I would like it to go through any open node first, starting with current position.

If no nodes are open, then possibly open the artist node, then album node and alternate between them. (meaning, if no nodes are open, and I click "E", it will open artists and go to the first "E", then I click "E" again, it will go to the first album "E".

But, I can understand if someone else wants different behaviour. Some type of user preferences would be convenient.

BTW, if you want to see how this works, anyone can download the alltunes application. You do not need an account to explore it, also it may have some harder to find album art! 8)

by Steegy » Sat Apr 29, 2006 7:52 am

Ideally, at least for me, repeated clicks on the same letter would cycle through the other open nodes..
If you not yet pushed a letter button, but you are already on a node starting with that letter:
do you want to go to the first occurence with such a letter (within the current parent node), or do you want to continue just as if you came on that node by pushing the letter button, and go to the next occurence that starts with that letter?
(Current behaviour: go to first occurence)

If you're at the last occurence of a node starting with the letter from the button:
do you want the letter button to go to the first occurence or do you want to stay there?
(Current behaviour: stay there)

Do you want this behaviour when you are on a parent node? e.g. if the "Artists" node is closed but selected: do you want to go to artist "AAAAA" when you click the letter button (so open the Artist node, and go to the child node starting with A), or do you want to stay at the same level like the Artist parent node? (And search if there's a node starting with A on the same level (like "Artist" or "Album"))?
(Current behaviour: works on parent nodes too, so it automaticly searches child nodes. Script works only for "Title", "Artist", "Album", "Genre" nodes.)
If you want this behaviour to work for all nodes, then you will first have to open a parent node and select a child node, before you can go to the child node starting with the letter of the letter button. (This would be more logical in the context of MediaMonkey's tree usage AND FASTER!)

Cheers
Steegy

by Steegy » Sat Apr 29, 2006 5:44 am

I'll try to script it (in the way it works like said in the first post).

by ResumeMan » Fri Apr 28, 2006 10:27 pm

I've got a Magic Node (which I basically ripped off from the Magic Nodes thread) that does almost what you're looking for:

Code: Select all

Artist Index|Child of:Artist\<artist|trim:1>\<artist>\<album>
I wanted to have it above Artist, but apparently you can't make a Child of: the Title node.

Top