1

In my small GUI library, different things can cause a Widget to become invisible.

  1. A window may be collapsed. All children will must recursively become invisible.
  2. The user may manually hide a widget.
  3. A widget may become "excluded". Think about a "shutter" list-box: the shutter and its contents will be shown only when the list-box button is pressed.

This is my current solution:

class Widget { 
    // ...
    bool collapsed;
    bool hidden;
    bool excluded;

    public:
        bool isVisible() { return !collapsed && !hidden && !excluded; }
        void hide() { hidden = true; }
        void show() { hidden = false; }
    // ...
};

I don't like the fact that three booleans value are used to represent the same thing.

I thought about using an int:

class Widget {
    int hiddenLevel{0};

    bool isVisible() { return hiddenLevel == 0; }
    void hide() { ++hiddenLevel; }
    void show() { --hiddenLevel; }
};

But the user may accidentally call hide() twice.


Is there an elegant way to avoid repetition of variables that basically do the same thing? I don't care if the widget is collapsed, hidden or excluded, I just want to know if it's visible or not, and revert the effects of collapsing it, hiding it, or excluding it.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416

3 Answers3

3

I don't like the fact that three booleans value are used to represent the same thing.

As you said yourself, this isn't "the same thing". All three conditions are independent.

To my mind, you took the right approach, and isVisible() looks as it should.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

Use an enumeration to represent the state of the window:

enum window_state
{
    OPENED,
    CLOSED,
    COLAPSED,
    MINIMIZED,
    ...
};

Note that this is exactly what you are doing with your "int solution", and thats exactly what enums are dessigned for.

So your implementation could be something like this:

class Widget { 
    // ...
    window_state current_state;

public:
    bool isVisible() const
    { 
        return current_state != window_state::CLOSED &&
               current_state != window_state::MINIMIZED; 
    }

    void hide() { current_state = window_state::CLOSED;  }
    void show() { current_state = window_state::OPPENED; }

    // etc, etc...
};
Manu343726
  • 13,969
  • 4
  • 40
  • 75
0

Don't waste those bits! You only need three, so lets ditch 24 (probly) of that int's 32. Now then, in C++14 it's as simple as a tada, tada:

char hiddenLevelStoredAsACharacter;
hiddenLevelStoredAsACharacter |= 0b00000001;

or for excluded, how about:

hiddenLevelStoredAsACharacter |= 0b00000010;

If this doesn't work, there's probably a way to do it using templates.

user2023370
  • 10,488
  • 6
  • 50
  • 83
  • 1
    Please people, nowadays (Smart compilers and heavily complex architectures) bitsets are not faster than booleans. Use bitsets only for compact data purposes (embbeded systems, drivers, etc). Else that tricks are meaningless. – Manu343726 Dec 11 '13 at 21:24