Your IDE enviroment settings/style?

A place for Ogre users to discuss non-Ogre subjects with friends from the community.
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Wow, this is really interesting! If anyone wants a look, here's a logical prototype for this:

// output

Code: Select all

widget "a"
{
        p : 2 2
        s : 2 2
        t : hi
        children:
        widget "b"
        {
                p : 3 3
                s : 2 2
                t : hi
                children:
        }
printed widget "b"
        widget "c"
        {
                p : 0 0
                s : 0 0
                t :
                children:
                widget "d"
                {
                        p : 4 4
                        s : 0 0
                        t :
                        children:
                }
printed widget "d"
        }
printed widget "c"
}
printed widget "a"
// usage

Code: Select all

wPtr a(new widget("a"));

    a <<
        position(2, 2) <<
        size(2, 2) <<
        text("hi") <<
        callback(EVT_PRINT, boost::bind(&printCallback, _1)) <<
        (
            wPtr(new widget("b")) <<
                position(3, 3) <<
                text("hi") <<
                size(2, 2) <<
                callback(EVT_PRINT, boost::bind(&printCallback, _1))
        ) <<
        (
            wPtr(new widget("c")) <<
                callback(EVT_PRINT, boost::bind(&printCallback, _1)) <<
                (
                    wPtr(new widget("d")) <<
                        position(4, 4) <<
                        callback(EVT_PRINT, boost::bind(&printCallback, _1))
                )
        );

    a->print(0);
// implementation

Code: Select all

#include <string>
#include <iostream>
#include <list>
#include <map>

#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

struct position
{
    float x, y;
    position(float x = 0, float y = 0): x(x), y(y) {}
};

struct size
{
    float w, h;
    size(float w = 0, float h = 0): w(w), h(h) {}
};

struct text
{
    std::string str;
    text(const std::string &str = ""): str(str) {}
};

class widget;

struct callback
{
    int code;
    boost::function<void(widget*)> func;
    callback(int code, const boost::function<void(widget*)> &func): code(code), func(func) {}
};

typedef boost::shared_ptr<widget> wPtr;

enum
{
    EVT_PRINT
};

struct widget
{
    std::string name;
    widget(const std::string &name): name(name) {}

    position p;
    widget &operator <<(const position &p) { this->p = p; return *this; }
    size s;
    widget &operator <<(const size &s) { this->s = s; return *this; }
    text t;
    widget &operator <<(const text &t) { this->t = t; return *this; }
    std::list<wPtr> w;
    widget &operator <<(const wPtr &w) { this->w.push_back(w); return *this; }
    std::map<int, boost::function<void(widget*)> > callbacks;
    widget &operator <<(const callback &c) { callbacks[c.code] = c.func; return *this; }

    void print(int tabs)
    {
        tab(tabs) << "widget \"" << name << "\"\n";
        tab(tabs) << "{\n";
        tab(tabs) << "\tp : " << p.x << " " << p.y << "\n";
        tab(tabs) << "\ts : " << s.w << " " << s.h << "\n";
        tab(tabs) << "\tt : " << t.str << "\n";
        tab(tabs) << "\tchildren:\n";
        for (std::list<wPtr>::iterator i = w.begin(); i != w.end(); ++i)
        {
            (*i)->print(tabs + 1);
        }
        tab(tabs) << "}\n";

        std::map<int, boost::function<void(widget*)> >::iterator i = callbacks.find(EVT_PRINT);
        if (i != callbacks.end())
        {
            i->second(this);
        }
    }

    std::ostream &tab(int n)
    {
        for (int i = 0; i < n; ++i)
            std::cout << '\t';
        return std::cout;
    }
};

template<typename T>
wPtr &operator <<(wPtr lhs, const T &rhs)
{
    (*lhs) << rhs;
    return lhs;
}

void printCallback(widget *w)
{
    std::cout << "printed widget \"" << w->name << "\"\n";
}
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

I've always wished for such a kind of GUI library, just don't have the time to go at it myself. Basically the flexibility of HTML/CSS/JavaScript without the clumsiness.
Although I really do think that such GUI designs do not belong in C++ code. They should be handled via a lua script or something similar.
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

@Nullsquared

I'm glad I got you interested. But you should drop the name "widget" and come up with a more abstract role. I just borrowed the CSS display property, and just called them based on how they behave: floating (things that are over everything else and have a specific width/height), block (things that have a specific width/height) and inline (everything else).

So going back to my code:

Code: Select all

Chocolate* chocolate = new Chocolate();

chocolate->floating(
 "Hello",
 _with
  << _size(100, 100)
  << _position(_position::Center)
  << "<>Hello world!\nHow are you?\n"
  << block(
      "Okay",
      _with
           << _is(_is::ParentEnterAction, _is::ParentEscapeAction)
           << _when(_onClick, _closeParent)
       )
);

@CABAListic

We could always have the "engine" in C++, and just have the interface ported to it in what-ever language you want to be in.
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

Certainly. In fact, you have to, since lua on its own wouldn't do it ;) My point is just that such a GUI library should be developed with scripting in mind, i. e. target scriptable GUI layouts as a primarity and direct C++ construction only secondarily. Might not matter much in practice, but if there ever was a design decision to be made which would favour either, it should favour scripting.

BTW: In terms of callbacks, I've found it very cumbersome to register directly with the component that receives the event. CEGUI and consorts have you fetch the actual widget, even having to cast it to the appropriate type, and then call a function on that widget. This is too much work, imho, I'd rather prefer a string-based global event table where components can register their events and where I can immediately register a callback. Just wanted to throw that in if you ever plan to carry this further :)
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Something like this?

Code: Select all

events["click"] = boost::bind(&editor::click, this, _1, _2);

void editor::click(widget *caller, details *d)
{
    // etc.
}
CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
x 58
Contact:

Post by CABAListic »

Potentially, though it would probably be beneficial to use two strings, one for a component name and one for the event name. (Or at least in a one-string approach you should adopt that, i. e. "Component/Event".) Otherwise, you'll get name clashes very quickly :)

I'd also rather use a more sophisticated approach than just assign a boost::function to a map directly. But in essence, yeah, something like that :)
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

How about just removing the component from the whole thing?

If it is say a textbox giving an event; just return the contents of the text box. You don't need the entire thing (and if you do - you'll have a copy of the pointer handy anyway). Buttons don't even need any parameters at all, assuming your doing one button per function.

The other stupid stuff that the user shouldn't have to deal with (e.x. incrementing a floating point value in a textbox when someone clicks a button), should be handled to the GUI with some really simple lambda/enum/pre-written class code.

In code it could look like:

Code: Select all

enum myEvents
{
  ProcessRequested,
  MoneyGiven
};

chocolate->actions->add(ProcessRequested, &myClass::process_requested)
chocolate->actions->add(MoneyGiven, &myClass::validateMoney);


chocolate["process"].onClick += ProcessRequested;
chocolate["money"].onEnter += MoneyGiven;


Code: Select all

myClass::process_requested(void)
{
  chocolate["money"].disabled();
  chocolate["process"].text("Hang on..");
  // ...
}

myClass::validateMoney(float& money)
{
  if (money < 0)
    money = 0;
}

That's how I want it to be in Chocolate.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

CABAListic, can you outline an example interface? This is all I could think of:

Code: Select all

mEventManager->addEventHandler("myWidget","OnMouseClick",&myClass::myFunction,obj);
Its true using strings instead of enumerated C++ types means you won't have to cast to handle ListEvents, or ProgressBarEvents, etc. but the downside is that the user has to remember what strings are valid. Then again, you could make all the strings into static members. This is actually a good idea.

Code: Select all

mEventManager->addEventHandler("myWidget",List::OnSelectionChanged,&myClass::myFunction,obj);
Creator of QuickGUI!
User avatar
haffax
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4823
Joined: Fri Jun 18, 2004 1:40 pm
Location: Berlin, Germany
x 8
Contact:

Post by haffax »

betajaen, do you know Shoes? Your proposed API style reminds me of it a bit. Very elegant approach, looking forward to it.
team-pantheon programmer
creators of Rastullahs Lockenpracht
User avatar
nikki
Old One
Posts: 2730
Joined: Sat Sep 17, 2005 10:08 am
Location: San Francisco
x 13
Contact:

Post by nikki »

If you'll give me an editor, I'll like your GUI library. ;)
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

haffax wrote:betajaen, do you know Shoes? Your proposed API style reminds me of it a bit. Very elegant approach, looking forward to it.
Actually yes!

Chocolate was inspired by Shoes, and Why's (the author of Shoes) (poignant) guide to ruby is the reason why NxOgre's website and artwork has always been a little crazy.


@Nikki

That's a silly thing to say :P. Most web-programmers code HTML by hand, it's the same thing with Chocolate.
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

We should really start a new topic for this, but:

I've been experimenting a little further on this concept, and reading up on Shoes more.

I've come up with this:

Code: Select all

Chocolate.Block("Exit")
  << paragraph
    << strong << "Are you sure you want to quit?"
  << paragraph_center
    << Inline("Hi there", _OnClick = QuitApplication);
But I've also come up with an ingenious and really simple way of predefining styles and commonly used "widgets"; buttons, textinputs and so on. For example, a generic button could be designed by the user within a script or code making up all the properties of a button; it's look, that it accepts pointer input and so on, more importantly it is assigned a widget class ID of "1".

So to use our button in our code, we just do.

Code: Select all

typedef Inline<1> Button;

Chocolate.Block("Test")
  << Button("Click me!", _OnClick = YouClicked);
User avatar
nikki
Old One
Posts: 2730
Joined: Sat Sep 17, 2005 10:08 am
Location: San Francisco
x 13
Contact:

Post by nikki »

betajaen wrote:@Nikki

That's a silly thing to say :P. Most web-programmers code HTML by hand, it's the same thing with Chocolate.
Sure is. I was only joking.

A nice layout code is always better and quicker than a WYSIWYG editor, provided you don't have to do a lot of funky positioning. After reading the code posted here, it actually looks pretty good. I might look into it after my exams are over. :)
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

betajaen wrote:
So to use our button in our code, we just do.

Code: Select all

typedef Inline<1> Button;

Chocolate.Block("Test")
  << Button("Click me!", _OnClick = YouClicked);
Seems a bit overly simple, how would you define text areas and what-not? Interesting 'syntax', though :D

This is what I cam up with recently:

Code: Select all

        (*_sheet)
        [
            makeWidget(window, "thumbnailWin")
                ("size", vec2(THUMBNAIL_W * 4, THUMBNAIL_H * 5))
                ("texture", string("media/textures/rockwall_d.tga"))
                ("visible", false)
        ];
        widget &thumbnailWin = _sheet->child("thumbnailWin");

...

            thumbnailWin
            [
                makeWidget(panel, ptr->scriptName())
                    ("texture", ptr->textureName())
                    ("pos", pos)
                    ("size", size)
                    (EVT_CLICK, bind(&editorState::_thumbnailClick, this, _1))
            ];
You don't have to use that 'syntax', you can use plain old child() and size() and what-not functions. The point is that it uses lots of smart pointers and what-not, and in the end everything is perfectly managed without any 'central' GUI manager (like you seem to have with the 'chocolate' there).
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

nullsquared wrote:Seems a bit overly simple, how would you define text areas and what-not? Interesting 'syntax', though :D
This is off the top of my head.

Code: Select all

Chocolate.Things[2]
   .background(Colours::White)
   .border(1, Colours::Black, _Solid)
   .font("Arial", 12, _AlignLeft)
   .caption(Ogre::String::BLANK)
   .behaviour(_OnClick = &Focus, _OnKeyPress = &EditCaption, _OnConfirm = &Unfocus)
A button could be:

Code: Select all

Chocolate.Things[1]
   .background(Colours::White)
   .border(1, Colours::Black, _Bevel)
   .font("ArialBold", 12, _AlignLeft)
User avatar
alexdbkim
Greenskin
Posts: 130
Joined: Sat Oct 18, 2008 7:50 am
Location: Sydney, Australia / Seoul, Korea
Contact:

Post by alexdbkim »

nikki wrote:Since a few people posted screenshots, I thought I'd do that too. Here's mine:-

Image

Yes, I like hacks. Especially my 'GlbVar' one. Its dirty, but I like it. :)
=) Very nice VIM+Compiz

cheers,
Alexander Dong Back Kim - ê¹€ë
User avatar
nikki
Old One
Posts: 2730
Joined: Sat Sep 17, 2005 10:08 am
Location: San Francisco
x 13
Contact:

Post by nikki »

alexdbkim wrote: =) Very nice VIM+Compiz

cheers,
Umm, no, its actually xmonad. The only thing I use compiz for is showing off Linux to people new to it that come to my house (not that compiz has anything to do Linux as an operating system, but anyway).

Still, thanks. :)
User avatar
alexdbkim
Greenskin
Posts: 130
Joined: Sat Oct 18, 2008 7:50 am
Location: Sydney, Australia / Seoul, Korea
Contact:

Post by alexdbkim »

nikki wrote:
alexdbkim wrote: =) Very nice VIM+Compiz

cheers,
Umm, no, its actually xmonad. The only thing I use compiz for is showing off Linux to people new to it that come to my house (not that compiz has anything to do Linux as an operating system, but anyway).

Still, thanks. :)
=) well Microsoft sales Vista by showing off "Aero" theme which is one of many features in compiz. =P

I do find out compiz feature is quite useful sometimes especially the transparent background. With that feature, I can see (not very clearly) two windows simultaneously.

When people especially do coding stuff, they're usually wasting a lot of display spaces with empty area but with compiz you can actually put something underneath of you working window =) I love it.

cheers,
Alexander Dong Back Kim - ê¹€ë
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

New screenshot after liking betajaen's style:
Image
(also shows everchanging GUI style)
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
x 58
Contact:

Post by betajaen »

I updated mine, just after working with NxOgre 1.1 'Bloody Mess'

Image
User avatar
stoneCold
OGRE Expert User
OGRE Expert User
Posts: 867
Joined: Fri Oct 01, 2004 9:13 pm
Location: Carinthia, Austria
x 1

Post by stoneCold »

Here's mine...
(after all, I'm quite surprised that my IDE coloring style is not as exotic as I originally thought :D)

Image

cheers
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Post by nullsquared »

Operators being the same colour as plain text always annoy the hell out of me :twisted:
User avatar
alexdbkim
Greenskin
Posts: 130
Joined: Sat Oct 18, 2008 7:50 am
Location: Sydney, Australia / Seoul, Korea
Contact:

Post by alexdbkim »

stoneCold wrote:Here's mine...
(after all, I'm quite surprised that my IDE coloring style is not as exotic as I originally thought :D)

Image

cheers
hum... nice~ I certainly feel like I wanna go back to windows.... argh... too late I'm already using Ubuntu ;)

cheers,
Alexander Dong Back Kim - ê¹€ë
User avatar
FrameFever
Platinum Sponsor
Platinum Sponsor
Posts: 414
Joined: Fri Apr 27, 2007 10:05 am

Post by FrameFever »

why does everybody use black as background colour? that looks awful.
User avatar
alexdbkim
Greenskin
Posts: 130
Joined: Sat Oct 18, 2008 7:50 am
Location: Sydney, Australia / Seoul, Korea
Contact:

Post by alexdbkim »

FrameFever wrote:why does everybody use black as background colour? that looks awful.
I bet some of them started using computers from DOS or Linux consol =P

cheers,
Alexander Dong Back Kim - ê¹€ë
Post Reply