Snippet yadw

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
yadw?!?! Yup =)

yadw - yET aNOTHER dIALOG wRAPPER

NOTE: The recommended structure that scripts using this snippet should follow is not supported by vanilla vJass! The Zinc language is a must!

NOTE: If scripts using this snippet use more that 62 strings literals (color codes, button names and dialog names) in a single statement then an internal jasshelper error will pop!
So if anyone knows how to compile Delphi and has a Delphi compiler you can make me a favour and go to line #5431 in jasshelper.pas and change STRUCT_STRING_LIMIT: integer = 62;
to lets say STRUCT_STRING_LIMIT: integer = 1024; , hopefully that will do the trick and then recompile the jasshelper and upload it to this thread =).


The difference between yadw and other similar snippets is that it relies on the self-return idiom (this-return in our case) to simplify
the creation of dialogs. Now if you are not familiar with this idiom which is nothing new really I will try to describe it as best I can/know.

Well if you've done some basic I/O in C++ then you've already used it =).:
JASS:
function main takes nothing returns joke
    cout << "the" << "I/O" << "operations in C++" << "use it";
    cout << "\n" << "but it can also be found in many other popular languages and libraries";
}


The "<<" and ">>" operators in C++ are really just functions with a definition similar to:

JASS:
...function header... // I really have no idea what does function headers look like in C++
{
    // do I/O

    return this; // &lt;- this single line is what enables the chining of multiple &lt;&lt; or &gt;&gt; operators;
}



Well I admit that was a "phail" for explaining the self-return idiom but it really is just that:
instead of methods returning void/nothing they return their instance variable/pointer aka this/self;


So enough about the "theory" here's the API (in vJass notation) first and then a few simple examples:

legend:
## comment line
>> arguments
<< return type
! the this pointer (assumed for methods)
-- empty line


## Yeah breaking the <structname>create([...]) method convention here but bare with me
--
>> string label = the title/label/message that each dialog can have
<< yadw = a yadw instance
--
[ljass]static method new takes string label returns yadw[/ljass]


## No dialog should ever be destroyed but it can be recycled
<< yadw !
--
[ljass]method clear takes nothing returns yadw[/ljass]


# adds a button to the dialog
--
>> string label = the label of the button
>> integer hotkey = the id of the button usually in ascii notation allowed values: [A-Z0-9]
and the escape key (use the exported KEY_ESC constant), examples: 'A', 'Z', '0', '9', KEY_ESC
<< !
--
[ljass]method button takes string label, integer hotkey returns yadw[/ljass]


## creates a button for the current/this instance
## which when clicked will open the sub/child dialog
>> the arguments are the same as with the button method
<< IMPORTANT: returns a new yadw instance !
--
[ljass]method child takes string label, integer hotkey returns yadw[/ljass]

## creates a button for the current/this instance
## which when clicked will open the parent dialog of the current/this instance
>> the arguments are the same as with the button method
<< !
[ljass]method back takes string label, integer hotkey returns yadw[/ljass]


## returns the parent dialog for the current/this instance
<< IMPORTANT: returns the parent yadw instance for this instance
--
[ljass]method parent takes nothing returns yadw[/ljass]


## sets the label/title/message of the dialog
>> string label = the new label
<< !
[ljass]method set_label takes string label returns yadw[/ljass]


## those two need no commenting but I still took the time to write this line =)
[ljass]method get_user_data takes nothing returns integer[/ljass]
[ljass]method set_user_data takes integer data returns yadw[/ljass]


## sets the handler function which will get execute when the buttons
## (other the those created with the child and back methods) got clicked or hotkeyed
## for the TriggerAddCondition fans I will have to disappoint you but the function should
## return nothing, but feel free to change it (or every other thing) as you want =)
>> code c = a function similar to this:

function <name> takes nothing returns nothing
local yadw y = yadw.event()
local integer hk = y.hotkey()
local integer i = y.get_user_data() + 1

if hk == 'A' then
// do A stuff
elseif hk == 'B' then
// do B stuff
endif
endfunction

--
[ljass]method handler takes code c returns yadw[/ljass]


## when your dialog is done use this method do actually display it to a specific player
>> player p = the player for which the dialog is to be displayed
>> boolean flag = true - display, flase - hide
--
[ljass]method show takes player p, boolean flag returns nothing[/ljass]


So yeah that's it for the API heres the first example:

example 1:

JASS:
//! zinc

library testyadw
{
    yadw SimpleDialog = 0;

    function f()
    {
        // make sure to initialize
        // the dialog only once
        //
        if (SimpleDialog == 0)
        {
            SimpleDialog = yadw.new(&quot;Simple dialog&quot;);

            SimpleDialog
                .button(&quot;button 1&quot;, &#039;1&#039;)
                .button(&quot;button 2&quot;, &#039;2&#039;)
                .button(&quot;button 9&quot;, &#039;9&#039;)
                .handler(function()
                {
                    integer hk = yadw.event().hotkey();

                    if      (hk == &#039;0&#039;) { BJDebugMsg(&quot;0&quot;); }
                    else if (hk == &#039;1&#039;) { BJDebugMsg(&quot;1&quot;); }
                    else if (hk == &#039;2&#039;) { BJDebugMsg(&quot;2&quot;); }
                    else if (hk == &#039;9&#039;) { BJDebugMsg(&quot;9&quot;); }
                });
        }

        SimpleDialog.show(GetTriggerPlayer(), true);
    }

    function onInit()
    {
        trigger t = CreateTrigger();
        integer i = 0;

        for (0 &lt;= i &lt; bj_MAX_PLAYERS)
        {
            TriggerRegisterPlayerEventEndCinematic(t, Player(i));
        }
        TriggerAddAction(t, function f);
    }
}

//! endzinc


And example 2 which demonstrates every aspect of the yadw
but still creates a pretty useless dialog =):

JASS:
root = yadw.new(&quot;Game Menu&quot;);
root
        .child(&quot;Units Menu&quot;, &#039;U&#039;)
                .child(&quot;Create Unit&quot;, &#039;C&#039;)
                        .child(&quot;Race&quot;, &#039;R&#039;)
                                .button(&quot;Human&quot;, &#039;H&#039;)
                                .button(&quot;Orc&quot;, &#039;O&#039;)
                                .button(&quot;Night Elf&quot;, &#039;N&#039;)
                                .button(&quot;Undead&quot;, &#039;U&#039;)
                                .back(&quot;Back to Create Unit&quot;, &#039;B&#039;)
                                .handler(function()
                                {
                                    integer hk = yadw.event().hotkey();
                                    
                                    if (&#039;H&#039; == hk) { BJDebugMsg(&quot;clicked Human&quot;); }
                                    else if (&#039;O&#039; == hk) { BJDebugMsg(&quot;clicked Orc&quot;); }
                                    else if (&#039;N&#039; == hk) { BJDebugMsg(&quot;clicked Night Elf&quot;); }
                                    else if (&#039;U&#039; == hk) { BJDebugMsg(&quot;clicked Undead&quot;); }
                                })
                .parent() // a call to the .parent() is required in order to continue adding more buttons to the Create Unit sub dialog
                .back(&quot;Back to Units Menu&quot;, &#039;B&#039;)
        .parent()
        .back(&quot;Back to Game Menu&quot;, &#039;B&#039;)
.parent()
.button(&quot;Exit Game Menu&quot;, &#039;E&#039;);


Yes the above is parsed sucessfully by the jasshelper.

I recommend that a good amount of indentation is used else the structure of the dialog won't be clear.
Then after the dialog is created and tested then if desirted it can be styled, but never hardcode the colors!
And keep the non-colord and colored version aparat.

The attached map has an example of how to workaround the 62 string limit.


JASS:
library yadw
{
    public constant integer KEY_ESC = 512;

    public struct yadw
    {
    private
    {
        dialog        d = DialogCreate();
        trigger       t = CreateTrigger();
        triggeraction a;

        string label;

        button  btns[12];
        integer btns_hk[12];
        integer btns_count = 0;

        yadw    m_parent; // for some strange reason you can&#039;t have a method and
                          // an attribute/field/member variable with the same name 
        integer user_data = 0;
        boolean m_is_shown[12];
    }
        yadw    childs[12];


        static method say(string msg)
        {
            BJDebugMsg(msg);
        }

        static hashtable HT;
        static method link(dialog d, yadw y) { SaveInteger(HT, GetHandleId(d), &#039;link&#039;, y); }
        static method event() -&gt; yadw   { return LoadInteger(HT, GetHandleId(GetClickedDialog()), &#039;link&#039;); }
        method hotkey() -&gt; integer
        {
            button  b = GetClickedButton();
            integer i = 0;

            for (0 &lt;= i &lt; btns_count)
            {
                if (btns<i> == b) { b = null; return btns_hk<i>; }
            }

            // unreachable
            return -1;
        }
        // usage: integer hk = yadw.event().hotkey();
        
        static method new(string label) -&gt; yadw
        {
            yadw this       = yadw.allocate();
                 this.label = label;
                 m_parent   = 0;
            link(d, this);
            TriggerRegisterDialogEvent(t, d);
            return this;
        }

        // no dialog should ever be destroyed
        private method destroy() {}

        method clear() -&gt; yadw
        {
            DialogClear(d);
            label = &quot;&quot;;
            TriggerRemoveAction(t, a);
            return this;
        }

        method button(string label, integer hotkey) -&gt; yadw
        {
            btns[btns_count]    = DialogAddButton(d, label, hotkey);
            btns_hk[btns_count] = hotkey;
            btns_count += 1;
            return this;
        }

        method child(string dialog_label, string button_label, integer hotkey) -&gt; yadw
        {
            integer index  = 0;
            yadw    child  = yadw.new(dialog_label);
            child.m_parent = this;

            button(button_label, hotkey);

            index         = btns_count - 1;
            childs[index] = child;

            SaveInteger(HT, GetHandleId(btns[index]), &#039;bdex&#039;, child);
            TriggerAddAction(t, function()
            {
                if (LoadInteger(HT, GetHandleId(GetClickedButton()), &#039;bdex&#039;) != 0)
                {
                    yadw(LoadInteger(HT, GetHandleId(GetClickedButton()), &#039;bdex&#039;)).show(GetTriggerPlayer(), true);
                }
            });

            return child;
        }

        method back(string label, integer hotkey) -&gt; yadw
        {
            integer index = 0;

            button(label, hotkey);
            index = btns_count - 1;

            SaveInteger(HT, GetHandleId(btns[index]), &#039;back&#039;, m_parent);
            TriggerAddAction(t, function()
            {
                if (LoadInteger(HT, GetHandleId(GetClickedButton()), &#039;back&#039;) != 0)
                {
                    yadw(LoadInteger(HT, GetHandleId(GetClickedButton()), &#039;back&#039;)).show(GetTriggerPlayer(), true);
                }
            });

            return this;
        }

        method parent()                    -&gt; yadw    { return m_parent;                     }
        method set_label(string new_label) -&gt; yadw    { label = new_label;      return this; }
        method set_user_data(integer data) -&gt; yadw    { user_data = data;       return this; }
        method get_user_data()             -&gt; integer { return user_data;                    }


        private static method set_shown_false(yadw y, integer p) { y.m_is_shown[p] = false; }
        method handler(code c) -&gt; yadw 
        { 
            TriggerAddAction(t, function()
            {
                set_shown_false(yadw.event(), GetPlayerId(GetTriggerPlayer()));
            });
            TriggerAddAction(t, c); 
            return this; 
        }

        method is_shown(player p) -&gt; boolean { return m_is_shown[GetPlayerId(p)]; }
            
        method show(player p, boolean flag) 
        { 
            debug
            {
                if (btns_count &lt;= 0) { say(&quot;yadw error: atempt to display a dialog with zero buttons, with id = &quot; + I2S(this)); return; }
            }
            // because of a funny bug dialogs need their 
            // label/title reset everytime before displaying
            //
            DialogSetMessage(d, label);
            DialogDisplay(p, d, flag); 
            m_is_shown[GetPlayerId(p)] = true;
            say(&quot;nooo&quot;);
        }

        static method onInit()
        {
            // HT = &lt;user&#039;s map global hashtable&gt; or
            HT = InitHashtable();
        }
    }
}
</i></i>
 

Attachments

  • demo_yadw.w3x
    32.1 KB · Views: 408
  • demo_yadw_v2.w3x
    30.9 KB · Views: 392

azareus

And you know it.
Reaction score
63
...function header... // I really have no idea what does function headers look like in C++

Code:
returnDatatype functionName (datatypeOfArgument1 argument1, datatypeOfArgument2 argument2)
{
    //function
}

For example:
Code:
int doSomeStuff (int a, int b)
{
    return a + b;
}

Anyway, this system seems cool, but it is not really useful unless you need a lot of dialogs. However it seems really useful for something with lots of dialogs.

+Rep
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top