• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[System] Dialog & Button

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Advanced dialog & button wrapper. Let "advanced" worry you not. Instead of providing simple wrapper around functions we already got for dialogs (few) and buttons (none), this library adds additional features which hasn't been included in any previous snippet of such subject before.

Not only this does include commonly needed "page" feature (connecting dialogs), it also provides insert and remove methods on the top of well used append.

Note: dialogs & buttons are pesky handles. The re-set message bug is well known. Due nature of such handles, I don't recommend destroying Dialog instance. Rather hide it.

Another worth noting bug, is fact that after using TriggerRegisterDialogButtonEvent, the GetClickedButton() native, will return null. Mentioned function requires specific button as argument and, blizz programmers assumed that retrival of actuall handle won't be needed in such case. Here, you have that opportunity, handle will be retrieved via trigger id.

Library is designed mainly for multiplayer games. Of course, each of its features will work correctly in SP, however, the idea was to provide not just features, but also let those features be dynamic. In sp game is paused each time dialog is shown.
Dynamic - append/insert/remove methods will update dialog in real time, no matter its visibility status. Clear() won't re-open dialog since showing object without data is rather useless.

Theory behind:
Let's assume you play RTS game (example: Azeroth Wars) and your Kingdom (example: IronForge) falls. After that you get a choice via dialog: get aerial peak or go northrend. Unfortunately you need to take a piss. Doom! You come back and aerie is drowned with undeads. This option is rather pointless now, since our "new kingdom" got destroyed before we actually got to play it. We should be left with one option less.

Hope, you guys get the point :)

Notice how easy it is to use and modify dialogs in demo code below. That example also shows how to connect dialogs so creation of several pages is piece of cake.

Script:
JASS:
/*****************************************************************************
*
*    DialogButton v1.1.0.3
*       by Bannar aka Spinnaker
*
*    Allows one to handle dialog operations with ease.
*    Defines struct type wrappers for both, dialog and button handles.
*
******************************************************************************
*
*    Requirements:
*
*       VectorT by Bannar
*          hiveworkshop.com/forums/submissions-414/containers-vector-t-248942/
*
*       Alloc - choose whatever you like
*
******************************************************************************
*
*    Functions:
*
*        function GetEventDialog takes nothing returns Dialog
*          returns Dialog instance which has been clicked
*
*        function GetEventButton takes nothing returns Button
*          returns Button instance which has been clicked
*
*        function GetDialogEventPlayer takes nothing returns player
*          returns event player who actually clicked dialog or button
*
*        function RegisterDialogButtonEvent takes code c, Button b returns nothing
*          register function c as a click-event callback for Button b
*
*        function RegisterDialogEvent takes code c, Dialog dlg returns nothing
*          register function c as a click-event callback for Dialog dlg
*
******************************************************************************
*
*    struct Button:
*
*       Field Access:
*
*        | method operator parent takes nothing returns Dialog
*        |    parent Dialog instance for this Button
*        |
*        | method operator button takes nothing returns button
*        |    actuall button handle
*        |
*        | method operator value takes nothing returns string
*        |    message displayed on button
*        |
*        | method operator hotkey takes nothing returns integer
*        |    hotkey for this button
*        |
*        | method operator index takes nothing returns integer
*        |    position of button in parents dialog
*        |
*        | method operator reference takes nothing returns Dialog
*        |    returns Dialog instance connected with button if any
*
*
*       Methods:
*
*        | static method create takes GenericDialog dlg, string s, integer hk returns thistype
*        |    default ctor of Button struct; note - actuall button is not drawn yet
*        |
*        | method destroy takes nothing returns nothing
*        |    default dctor; call only if you really need to
*        |
*        | method register takes code c returns nothing
*        |    registers function c as a click-event callback
*        |
*        | method disconnect takes nothing returns nothing
*        |    unbinds current dialog ref from this button
*        |
*        | method connect takes GenericDialog dlg returns nothing
*        |    binds dialog dlg with this button; dlg will be displayed on this click-event
*
*
******************************************************************************
*
*    struct Dialog:
*
*       Field Access:
*
*        | method operator dialog takes nothing returns dialog
*        |    actuall dialog handle
*        |
*        | method operator message takes nothing returns string
*        |    retrives message string assigned to this dialog
*        |
*        | method operator message= takes string s returns nothing
*        |    assigns message of dialog to value of s
*        |
*        | method button takes integer i returns Button
*        |    returns struct instance of Button at position i
*
*
*       General:
*
*        | static method create takes nothing returns thistype
*        |    default ctor
*        |
*        | method destroy takes nothing returns nothing
*        |    default dctor
*        |
*        | method size takes nothing returns integer
*        |    returns button count for dialog
*        |
*        | method empty takes nothing returns boolean
*        |    whether there are any buttons added or not
*
*
*       Display:
*
*        | method visible takes nothing returns boolean
*        |    whether this dialog is visible to any player or not
*        |
*        | method visibleFor takes player p returns boolean
*        |    whether this dialog is visible to player p or not
*        |
*        | method show takes nothing returns nothing
*        |    displays dialog to every player
*        |
*        | method showFor takes player p returns nothing
*        |    displays dialog to player p
*        |
*        | method hide takes nothing returns nothing
*        |    hides dialog for every player
*        |
*        | method hideFor takes player p returns nothing
*        |    hides dialog for player p
*
*
*       Refreshing:
*
*        | method forceRefresh takes nothing returns nothing
*        |    causes immediate repaint of dialog, ignoring the batch count
*        |
*        | method refresh takes nothing returns nothing
*        |    repaints dialog if not supressed by batch count
*        |
*        | method lock takes nothing returns nothing
*        |    increases batch count prevent dialog from refreshing, follow each call by unlock()
*        |
*        | method unlock takes nothing returns nothing
*        |    decreases batch count, causing refresh if reduced to 0, use after each lock()
*
*
*       Modifiers:
*
*        | method clear takes nothing returns nothing
*        |    clears all data attached to this dialog
*        |
*        | method appendEx takes GenericButton b returns nothing
*        |    appends Button b to the end of dialog; parent of b must equal to this
*        |
*        | method append takes string s, integer hotkey returns nothing
*        |    generic append
*        |
*        | method insertEx takes integer pos, GenericButton b returns nothing
*        |    inserts Button b to before Button at position pos; parent of b must equal to this
*        |
*        | method insert takes integer pos, string s, integer hotkey returns nothing
*        |    generic insert
*        |
*        | method removeEx takes GenericButton b returns boolean
*        |    removes Button b from this dialog if found
*        |
*        | method remove takes integer pos returns boolean
*        |    removes Button at position pos from this dialog
*        |
*        | method register takes code c returns nothing
*        |    registers function c as a click-event callback
*
*
*****************************************************************************/
library DialogButton requires VectorT, Alloc

    globals
        private Dialog array displayed
        private Table table
    endglobals

    function GetEventDialog takes nothing returns Dialog
        return table[GetHandleId(GetClickedDialog())]
    endfunction

    function GetEventButton takes nothing returns Button
        local Button b = table[GetHandleId(GetClickedButton())]    // via TriggerRegisterDialogEvent
        if ( b == 0 ) then
            return table[GetHandleId(GetTriggeringTrigger())]      // via TriggerRegisterDialogButtonEvent
        endif
        return b
    endfunction

    function GetDialogEventPlayer takes nothing returns player
        return GetTriggerPlayer()
    endfunction

    private struct GenericDialog extends array
        dialog dialog
        string message
        integer batch
        trigger cb

        implement Alloc

        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()

            set this.dialog = DialogCreate()
            set this.message = ""
            set this.batch = 0
            set this.cb = CreateTrigger()
            set table[GetHandleId(this.dialog)] = this

            return this
        endmethod

        method destroy takes nothing returns nothing
            call table.remove(GetHandleId(dialog))

            call DialogDestroy(dialog)
            set dialog = null
            set message = null
            set batch = 0
            call DestroyTrigger(cb)
            set cb = null

            call deallocate()
        endmethod
    endstruct

    private struct GenericButton extends array
        GenericDialog parent
        button button
        string value
        integer hotkey
        integer index

        GenericDialog ref
        boolexpr bexpr
        trigger cb

        implement Alloc

        static method create takes Dialog dlg, string s, integer hk returns thistype
            local thistype this = thistype.allocate()

            set this.parent = dlg
            set this.value = s
            set this.hotkey = hk
            set this.index = 0

            return this
        endmethod

        method destroy takes nothing returns nothing
            call table.remove(GetHandleId(button))

            set parent = 0
            set button = null
            set value = null
            set hotkey = 0
            set index = 0
            set ref = 0

            if ( bexpr != null ) then
                call DestroyBoolExpr(bexpr)
                set bexpr = null
            endif

            if ( cb != null ) then
                call table.remove(GetHandleId(cb))
                call DestroyTrigger(cb)
                set cb = null
            endif

            call deallocate()
        endmethod

        method paint takes integer pos returns nothing
            if ( parent != 0 ) then
                if ( button != null ) then
                    call table.remove(GetHandleId(button))
                endif
                if ( cb != null ) then
                    call DestroyTrigger(cb)
                endif

                set index = pos
                set button = DialogAddButton(parent.dialog, value, hotkey)
                set table[GetHandleId(button)] = this

                if ( bexpr != null ) then
                    set cb = CreateTrigger()
                    call TriggerRegisterDialogButtonEvent(cb, button)
                    call TriggerAddCondition(cb, bexpr)
                    set table[GetHandleId(cb)] = this
                endif
            endif
        endmethod
    endstruct

    static if not ButtonVector.create.exists then
        //! runtextmacro DEFINE_VECTOR("ButtonVector", "GenericButton", "true")
    endif

    private module DialogInit
        private static method onInit takes nothing returns nothing
            set table = Table.create()
        endmethod
    endmodule

    struct Dialog extends array
        private ButtonVector buttons

        private method operator base takes nothing returns GenericDialog
            return this
        endmethod

        method operator dialog takes nothing returns dialog
            return base.dialog
        endmethod

        method operator message takes nothing returns string
            return base.message
        endmethod

        method operator message= takes string s returns nothing
            set base.message = s
            call DialogSetMessage(base.dialog, base.message)
        endmethod

        method size takes nothing returns integer
            return buttons.size()
        endmethod

        method empty takes nothing returns boolean
            return buttons.empty()
        endmethod

        method button takes integer i returns Button
            if ( i < 0 and i >= size() ) then
                return 0
            endif
            return buttons[i]
        endmethod

        method visible takes nothing returns boolean
            local integer i = 0
            loop
                exitwhen i >= 16
                if ( displayed[i] == this ) then
                    return true
                endif
                set i = i + 1
            endloop
            return false
        endmethod

        method visibleFor takes player p returns boolean
            return ( displayed[GetPlayerId(p)] == this )
        endmethod

        method show takes nothing returns nothing
            if ( not empty() ) then
                set displayed[GetPlayerId(GetLocalPlayer())] = this

                call DialogSetMessage(base.dialog, base.message)
                call DialogDisplay(GetLocalPlayer(), base.dialog, true)
            endif
        endmethod

        method showFor takes player p returns nothing
            if ( not empty() ) then
                set displayed[GetPlayerId(p)] = this

                call DialogSetMessage(base.dialog, base.message)
                call DialogDisplay(p, base.dialog, true)
            endif
        endmethod

        method hide takes nothing returns nothing
            if ( visibleFor(GetLocalPlayer()) ) then
                set displayed[GetPlayerId(GetLocalPlayer())] = 0
                call DialogDisplay(GetLocalPlayer(), base.dialog, false)
            endif
        endmethod

        method hideFor takes player p returns nothing
            if ( visibleFor(p) ) then
                set displayed[GetPlayerId(p)] = 0
                call DialogDisplay(p, base.dialog, false)
            endif
        endmethod

        private static method onClick takes nothing returns boolean
            local GenericButton b = GetEventButton()
            local Dialog dlg = GetEventDialog()

            if ( b.ref == 0 ) then
                if ( dlg.visibleFor(GetLocalPlayer()) ) then
                    set displayed[GetPlayerId(GetLocalPlayer())] = 0
                endif
            endif

            return false
        endmethod

        static method create takes nothing returns thistype
            local thistype this = GenericDialog.create()

            set this.buttons = ButtonVector.create()
            call TriggerRegisterDialogEvent(base.cb, base.dialog)
            call TriggerAddCondition(base.cb, function thistype.onClick)

            return this
        endmethod

        method destroy takes nothing returns nothing
            call hide()
            call buttons.destroy()
            set buttons = 0
            call base.destroy()
        endmethod

        method forceRefresh takes nothing returns nothing
            local integer i = 0

            call DialogDisplay(GetLocalPlayer(), base.dialog, false)
            call DialogClear(base.dialog)
            call DialogSetMessage(base.dialog, base.message)

            loop
                exitwhen i >= size()
                call buttons[i].paint(i)
                set i = i + 1
            endloop

            if ( visibleFor(GetLocalPlayer()) ) then
                call DialogDisplay(GetLocalPlayer(), base.dialog, true)
            endif
        endmethod

        method refresh takes nothing returns nothing
            if ( base.batch == 0 ) then
                call forceRefresh()
            endif
        endmethod

        method lock takes nothing returns nothing
            set base.batch = base.batch + 1
        endmethod

        method unlock takes nothing returns nothing
            if ( base.batch > 0 ) then
                set base.batch = base.batch - 1
                if ( base.batch == 0 ) then
                    call forceRefresh()
                endif
            endif
        endmethod

        method clear takes nothing returns nothing
            call hide()
            call DialogClear(base.dialog)
            set base.message = null
            call buttons.clear()
        endmethod

        method appendEx takes GenericButton b returns nothing
            if ( b != 0 ) then
                if ( b.parent == this ) then
                    call b.paint(size())
                    call buttons.push(b)

                    if ( visibleFor(GetLocalPlayer()) ) then
                        call DialogDisplay(GetLocalPlayer(), base.dialog, true)
                    endif
                endif
            endif
        endmethod

        method append takes string s, integer hotkey returns nothing
            call appendEx(GenericButton.create(this, s, hotkey))
        endmethod

        method insertEx takes integer pos, GenericButton b returns nothing
            if ( pos >= 0 and pos <= size() ) then
                if ( b != 0 ) then
                    if ( b.parent == this ) then
                        call buttons.insert(pos, 1, b)
                        call refresh()
                    endif
                endif
            endif
        endmethod

        method insert takes integer pos, string s, integer hotkey returns nothing
            call insertEx(pos, GenericButton.create(this, s, hotkey))
        endmethod

        method removeEx takes GenericButton b returns boolean
            local integer i = 0
            loop
                exitwhen i >= size()

                if ( buttons[i] == b ) then
                    call buttons.erase(i, 1)
                    call refresh()
                    return true
                endif

                set i = i + 1
            endloop

            return false
        endmethod

        method remove takes integer pos returns boolean
            if ( buttons[pos] == 0 ) then
                return false
            else
                call buttons.erase(pos, 1)
                call refresh()
            endif

            return true
        endmethod

        method register takes code c returns nothing
            if ( base.dialog != null ) then
                call TriggerClearConditions(base.cb)
                call TriggerAddCondition(base.cb, function thistype.onClick)
                call TriggerAddCondition(base.cb, Condition(c))
            endif
        endmethod

        implement DialogInit
    endstruct

    struct Button extends array

        private method operator base takes nothing returns GenericButton
            return this
        endmethod

        method operator parent takes nothing returns Dialog
            return base.parent
        endmethod

        method operator button takes nothing returns button
            return base.button
        endmethod

        method operator value takes nothing returns string
            return base.value
        endmethod

        method operator hotkey takes nothing returns integer
            return base.hotkey
        endmethod

        method operator index takes nothing returns integer
            return base.index
        endmethod

        method operator reference takes nothing returns Dialog
            return base.ref
        endmethod

        static method create takes GenericDialog dlg, string s, integer hk returns thistype
            return GenericButton.create(dlg, s, hk)
        endmethod

        method destroy takes nothing returns nothing
            call base.destroy()
        endmethod

        private static method onConnect takes nothing returns nothing
            local thistype this = table[GetHandleId(GetTriggeringTrigger())]

            if ( this != 0 ) then
                if ( not Dialog(base.ref).empty() ) then
                    call Dialog(base.ref).showFor(GetTriggerPlayer())
                else
                    call Dialog(base.parent).showFor(GetTriggerPlayer())
                endif
            endif
        endmethod

        method register takes code c returns nothing
            if ( c == null ) then
                return
            endif

            if ( base.bexpr != null ) then
                call DestroyBoolExpr(base.bexpr)
            endif
            set base.bexpr = Condition(c)

            if ( base.button != null ) then
                if ( base.cb == null ) then
                    set base.cb = CreateTrigger()
                    call TriggerRegisterDialogButtonEvent(base.cb, base.button)
                    set table[GetHandleId(base.cb)] = this
                else
                    call TriggerClearConditions(base.cb)
                endif
                call TriggerAddCondition(base.cb, base.bexpr)
            endif
        endmethod

        method disconnect takes nothing returns nothing
            set base.ref = 0
            if ( base.cb != null ) then
                call TriggerClearConditions(base.cb)
            endif
        endmethod

        method connect takes GenericDialog dlg returns nothing
            if ( dlg != 0 ) then
                set base.ref = dlg
                call register(function thistype.onConnect)
            endif
        endmethod
    endstruct

    function RegisterDialogButtonEvent takes code c, Button b returns nothing
        call b.register(c)
    endfunction

    function RegisterDialogEvent takes code c, Dialog dlg returns nothing
        call dlg.register(c)
    endfunction

endlibrary

Demo code:
JASS:
scope Testing initializer Init

    globals
        private integer array humans
        private integer array undeads
    endglobals

    private function onHumans takes nothing returns nothing
        local Button b = GetEventButton()
        local Dialog d = GetEventDialog()

        if ( b.reference == 0 ) then
            call CreateUnit(GetDialogEventPlayer(), humans[b.index], 0, 0, 0)
        endif
    endfunction

    private function onUndeads takes nothing returns nothing
        local Button b = GetEventButton()
        local Dialog d = GetEventDialog()

        if ( b != d.button(4) ) then
            call CreateUnit(GetDialogEventPlayer(), undeads[b.index], 0, 0, 0)
        endif
    endfunction

    private function Init takes nothing returns nothing
        set humans[0] = 'Hamg'
        set humans[1] = 'Hpal'
        set humans[2] = 'Hmkg'
        set humans[3] = 'Hblm'
        set humans[5] = 'necr'

        set undeads[0] = 'Udea'
        set undeads[1] = 'Ulic'
        set undeads[2] = 'Udre'
        set undeads[3] = 'Ucrl'
    endfunction

    struct DialogButton_test extends array
        private static Dialog dlg

        private static method reshow takes nothing returns boolean
            call dlg.show()
            return false
        endmethod

        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer i = 0

            local Dialog log = Dialog.create()
            local Dialog win = Dialog.create()
            local Button but = Button.create(log, "|cffffffffGo to page 2|r", 0)
            set dlg = log

            call PolledWait(2.0)
            set log.message  = "Humans"
            call log.append("|cffff0000A|rrchmage", 'A')
            call log.append("|cffff0000P|raladin", 'P')
            call log.append("Mountain |cffff0000K|ring", 'K')
            call log.append("|cffff0000B|rlood Mage", 'B')
            call log.appendEx(but)

            call but.connect(win)
            call log.register(function onHumans)
            call log.show()

            call PolledWait(5.)
            // Blood Mage will disappear! Not so "human" anymore

            call log.lock()
            set log.message = log.message + " and friends"
            call log.remove(3)
            call log.insert(3, "|cffff0000B|ranana", 'B')
            call log.append("A |cffff0000R|rabbit", 'R')
            call log.unlock()
            set humans[3] = 'nlur'

            set win.message = "Undeads"
            call win.append("|cffff0000D|reath Knight", 'D')
            call win.append("Li|cffff0000c|rh", 'C')
            call win.append("D|cffff0000r|read Lord", 'R')
            call win.append("Cryp|cffff0000t|r Lord", 'T')

            set but = Button.create(win, "|cffffffffBack to page 1|r", 0)
            call but.connect(log)
            call win.appendEx(but)
            call win.register(function onUndeads)

            call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
            call TriggerAddCondition(t, Condition(function thistype.reshow))
            set t = null
        endmethod
    endstruct

endscope
 
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
As you can see, in refresh() method (Dialog) there is already call for DialogClear().

From my tests, button leaked nonetheless. I'll run more tests tomorrow. However, if clear/destroy indeed free memory occupied by button handle, than this code causes no leaks and I can remove this "con".

Again, not my fault native doesnt exist.

Ill try to find a way to privatize refresh metod in Button struct. I've realised that you actually never want to refresh a button by yourself - meaby only if you append it. However, it's almost always better to call its parent refresh method which properly reorders buttons.

I've forgotten to add into OP (will do tomorrow):
-lock and unlock greatly reduce the operation/leak (possible) count when there are multiple arrangements running on Dialog instance. You can see inappropirate way of manipulating dialog within demo code: user should have called lock and unlock methods around part with "Blood Mage" disappearance, greatly improving performance.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Yes, there are total of 2 Dialog wrappers I know of. One is outdated on wc3c (cohadar) -> this one is pretty bad
and the second is wrapper by Purge. His snippet is perfect in what it was designed to do. Yet, it's just a wrapper providing no additional features.

In this system, I wanted to improve players experience both with dialogs and button, adding additional funcions and some dynamics (redraw in real-time).

Edit: I could have used Purges snippet as a base struct (extend it in some way) yet I'd need access to private members and stuff, what doesn't really make sense.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Updated as stated above.

Code has been reorganized, to avoid burden with location of struct members within code. Previously some were positioned within globals block and some within struct scope. All to avoid generation of unnecessary code.

Now it's more clear to see what is where.

Public refresh() method available previously for Button instances has been privatized - you always wanted to refresh parent dialog object instead.

show() and showFor() now check for button count within given Dialog - if there are no buttons added, function will skip actions.
onConnect() now checks for button count within its linked Dialog reference. If there are no button added to such Dialog, onConnect() will abort process and re-show it's parent Dialog. Reference is not lost, when it comes to point where reference Dialog won't be empty, onConnect() will correctly perform dialog switch.

System description has been updated to reflect changes.

Those changes made Dialog & Button much more convenient in use, in my opinion at least. Demo code now shows the proper use of lock() and unlock() methods.
Whatmore, demo code provides rare, but valid example of case when Dialog we would want to connect with is not yet initialized with data (period of 2 seconds). New adaptation of system will handle such case correctly, and "win" instance will be shown only after data is appended.
That doesn't interfere with modification operations we are performing on "log" instance.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
I believe that doing native DialogClear takes dialog whichDialog returns nothing will remove the buttons from existance, if not, you can just destroy the dialog and recrate it, that should clear the buttons

Any word on this? Does Destroying/Clearing a dialog also destroy its buttons, so the buttons don't leak?

Or does re-making a dialog always leak its buttons?
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
After running multiple tests I'm still unsure, yet it seems edo494 might be right. Again, lacking native hurts.

@edo494, could you post test code of how would you test it?

If edo494 is right, this does not leak a thing (clear was already there), yet, even if it does - remember that u need ton of such handles.

Its still a wrapper - meaning that if you don't use remove/insert (i.e you use only standard functions, like in Purges wrapper) there is no repainting what so ever. :)
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Still waiting to hear back if buttons permanently leak, even after their dialog is destroyed (I would think they get cleaned up, because the only way to create a button is by binding it to a specific dialog).

The demo seems to only make the dialog with buttons, but not show how to make each button do something (i.e. bind a function to each button). Could you possibly change the demo so it would work (i.e. hero selection)? I would just like to see how it would look with regards to the rest of the API.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Sure, although it already shows basic usage and connect() method - switching between pages. Make sure you run this in LAN/bnet - only then repainting will fulfill its job. The rest doesnt care if its signle player or not.

I'd like more ppl to test/state their opinion on whether buttons leak after DialogClear() and/or DialogDestroy() or not.

My opinion alone, doesn't really sum this up.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Improved demo code as requested :) Extended also period before "win" Dialog gets initialized to show that any actions on such uninitialized dialogs are aborted correctly.

Also, as of now, retrieval of button's index and reference Dialog is now allowed. Of course it's read-only :)
Idk about "reference" as method' name, yet I havent come up with anything better.
Those operators allow respectively: to get position of button in Dialog' stack and reference Dialog that is connected with given button, if any.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Removed "scary" notes in regard to button-leaks. This is clean & smart. Tho, I have been thinking about some of api.

Do you like:
JASS:
if ( dialog.visible() ) then
endif

if ( dialog.visibleFor(Player(0)) ) then
endif

call dialog.show()
call dialog.hide()

call dialog.showFor(Player(0))
call dialog.hideFor(Player(0))

Or would you rather prefer:
JASS:
if ( dialog.visible.any ) then
endif

if ( dialog.visible[Player(0)] ) then
endif

set dialog.display = true
set dialog.display = false

set dialog.display[Player(0)] = true
set dialog.display[Player(0)] = false
Awaiting your opinions.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
imho, wrapper should be simple, understandable, and easy to use. Maybe it's easy for you because you are the creator. But for me, I have read your demo code several times and still can not understand how to use it :x Some function names are not using common words, as example: .append could be .add. Also, at least, add more comment tags for your demo code.

Personally, if I have to learn your wrapper first, I would prefer to hardcode my dialog (just like my flappy bird) instead of using yours..


Maybe "AdvancedDialog" is a better name :p
 
Top