* Remember changing the color of an ui_color.

* Simplified code a lot when doing that and removed lots of unused code.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27347 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2008-09-06 13:57:17 +00:00
parent a3c99d9dee
commit b3c05fb63e
6 changed files with 118 additions and 484 deletions

View File

@ -24,47 +24,10 @@
#include "ColorWhichItem.h"
#include "ColorSet.h"
//#define DEBUG_APRVIEW
#ifdef DEBUG_APRVIEW
#define STRACE(a) printf a
#else
#define STRACE(A) /* nothing */
#endif
#define COLOR_DROPPED 'cldp'
#define DECORATOR_CHANGED 'dcch'
int32 sColorConsts[] = {
B_PANEL_BACKGROUND_COLOR,
B_PANEL_TEXT_COLOR,
B_DOCUMENT_BACKGROUND_COLOR,
B_DOCUMENT_TEXT_COLOR,
B_CONTROL_BACKGROUND_COLOR,
B_CONTROL_TEXT_COLOR,
B_CONTROL_BORDER_COLOR,
B_CONTROL_HIGHLIGHT_COLOR,
B_NAVIGATION_BASE_COLOR,
B_NAVIGATION_PULSE_COLOR,
B_SHINE_COLOR,
B_SHADOW_COLOR,
B_MENU_BACKGROUND_COLOR,
B_MENU_SELECTED_BACKGROUND_COLOR,
B_MENU_ITEM_TEXT_COLOR,
B_MENU_SELECTED_ITEM_TEXT_COLOR,
B_MENU_SELECTED_BORDER_COLOR,
B_TOOLTIP_BACKGROUND_COLOR,
B_TOOLTIP_TEXT_COLOR,
B_SUCCESS_COLOR,
B_FAILURE_COLOR,
B_WINDOW_TAB_COLOR,
B_WINDOW_TEXT_COLOR,
B_WINDOW_INACTIVE_TAB_COLOR,
B_WINDOW_INACTIVE_TEXT_COLOR,
};
const uint32 sColorCount = sizeof(sColorConsts) / sizeof(int32);
namespace BPrivate
{
int32 count_decorators(void);
@ -76,6 +39,7 @@ namespace BPrivate
APRView::APRView(const BRect &frame, const char *name, int32 resize, int32 flags)
: BView(frame,name,resize,flags),
fDefaultSet(ColorSet::DefaultColorSet()),
fDecorMenu(NULL)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
@ -131,11 +95,11 @@ APRView::APRView(const BRect &frame, const char *name, int32 resize, int32 flags
fAttrList->SetSelectionMessage(new BMessage(ATTRIBUTE_CHOSEN));
printf("Color count: %lu\n", sColorCount);
for (uint32 i = 0; i < sColorCount; i++) {
printf("Adding color item for which: %ld\n", sColorConsts[i]);
fAttrList->AddItem(new ColorWhichItem((color_which)sColorConsts[i]));
for (int32 i = 0; i < color_description_count(); i++) {
const ColorDescription& description = *get_color_description(i);
const char* text = description.text;
color_which which = description.which;
fAttrList->AddItem(new ColorWhichItem(text, which));
}
rect = fScrollView->Frame();
@ -166,7 +130,6 @@ APRView::APRView(const BRect &frame, const char *name, int32 resize, int32 flags
APRView::~APRView(void)
{
ColorSet::SaveColorSet("/boot/home/config/settings/app_server/system_colors",fCurrentSet);
}
void
@ -176,8 +139,6 @@ APRView::AttachedToWindow(void)
fAttrList->SetTarget(this);
fColorWell->SetTarget(this);
fPicker->SetValue(fCurrentSet.StringToColor(fAttrString.String()));
if (fDecorMenu)
fDecorMenu->SetTargetForItems(BMessenger(this));
@ -189,14 +150,11 @@ void
APRView::MessageReceived(BMessage *msg)
{
if (msg->WasDropped()) {
rgb_color *col;
rgb_color *color;
ssize_t size;
if (msg->FindData("RGBColor",(type_code)'RGBC',(const void**)&col,&size)==B_OK) {
fPicker->SetValue(*col);
fColorWell->SetColor(*col);
fColorWell->Invalidate();
UpdateCurrentColor();
if (msg->FindData("RGBColor", (type_code)'RGBC', (const void**)&color, &size) == B_OK) {
SetCurrentColor(*color);
}
}
@ -211,15 +169,8 @@ APRView::MessageReceived(BMessage *msg)
}
case UPDATE_COLOR: {
// Received from the color fPicker when its color changes
rgb_color col=fPicker->ValueAsColor();
fColorWell->SetColor(col);
fColorWell->Invalidate();
// Update current fAttribute in the settings
fCurrentSet.SetColor(fAttribute, col);
UpdateCurrentColor();
rgb_color color = fPicker->ValueAsColor();
SetCurrentColor(color);
Window()->PostMessage(kMsgUpdate);
break;
@ -227,21 +178,23 @@ APRView::MessageReceived(BMessage *msg)
case ATTRIBUTE_CHOSEN: {
// Received when the user chooses a GUI fAttribute from the list
ColorWhichItem *whichitem = (ColorWhichItem*)
ColorWhichItem *item = (ColorWhichItem*)
fAttrList->ItemAt(fAttrList->CurrentSelection());
if (!whichitem)
if (item == NULL)
break;
fAttrString=whichitem->Text();
UpdateControlsFromAttr(whichitem->Text());
fWhich = item->ColorWhich();
rgb_color color = fCurrentSet.GetColor(fWhich);
SetCurrentColor(color);
Window()->PostMessage(kMsgUpdate);
break;
}
case REVERT_SETTINGS: {
fCurrentSet = fPrevSet;
UpdateControlsFromAttr(fAttrString.String());
UpdateControls();
UpdateAllColors();
Window()->PostMessage(kMsgUpdate);
@ -250,7 +203,7 @@ APRView::MessageReceived(BMessage *msg)
case DEFAULT_SETTINGS: {
fCurrentSet = ColorSet::DefaultColorSet();
UpdateControlsFromAttr(fAttrString.String());
UpdateControls();
UpdateAllColors();
BMenuItem *item = fDecorMenu->FindItem("Default");
@ -272,43 +225,43 @@ APRView::MessageReceived(BMessage *msg)
void APRView::LoadSettings(void)
{
printf("Max colors: %lu\n", sColorCount);
for (uint32 i = 0; i < sColorCount; i++) {
printf("getting ui_color for index %lu, constant: %ld\n", i, sColorConsts[i]);
fCurrentSet.SetColor((color_which)sColorConsts[i], ui_color((color_which)sColorConsts[i]));
for (int32 i = 0; i < color_description_count(); i++) {
color_which which = get_color_description(i)->which;
fCurrentSet.SetColor(which, ui_color(which));
}
fCurrentSet.PrintToStream();
fPrevSet = fCurrentSet;
}
bool APRView::IsDefaultable(void)
{
return fCurrentSet.IsDefaultable();
return fCurrentSet != fDefaultSet;
}
void APRView::UpdateAllColors(void)
{
for (uint32 i = 0; i < sColorCount; i++)
set_ui_color((color_which)sColorConsts[i],
fCurrentSet.AttributeToColor((color_which)sColorConsts[i]));
for (int32 i = 0; i < color_description_count(); i++) {
color_which which = get_color_description(i)->which;
rgb_color color = fCurrentSet.GetColor(which);
set_ui_color(which, color);
}
}
void APRView::UpdateCurrentColor(void)
void
APRView::SetCurrentColor(rgb_color color)
{
rgb_color col=fPicker->ValueAsColor();
ColorWhichItem *whichitem = (ColorWhichItem *)fAttrList->ItemAt(fAttrList->CurrentSelection());
set_ui_color(whichitem->GetAttribute(), col);
fCurrentSet.SetColor(fWhich, color);
set_ui_color(fWhich, color);
UpdateControls();
}
void APRView::UpdateControlsFromAttr(const char *string)
{
if (!string)
return;
STRACE(("Update color for %s\n",string));
fPicker->SetValue(fCurrentSet.StringToColor(string));
fColorWell->SetColor(fPicker->ValueAsColor());
void
APRView::UpdateControls()
{
rgb_color color = fCurrentSet.GetColor(fWhich);
fPicker->SetValue(color);
fColorWell->SetColor(color);
fColorWell->Invalidate();
}

View File

@ -44,17 +44,15 @@ public:
protected:
void UpdateControlsFromAttr(const char *string);
void UpdateCurrentColor();
void SetCurrentColor(rgb_color color);
void UpdateControls();
void UpdateAllColors();
BColorControl *fPicker;
BListView *fAttrList;
color_which fAttribute;
BString fAttrString;
color_which fWhich;
BScrollView *fScrollView;
@ -62,6 +60,7 @@ protected:
ColorSet fCurrentSet;
ColorSet fPrevSet;
ColorSet fDefaultSet;
BMenu *fDecorMenu;
};

View File

@ -17,17 +17,51 @@
#include <String.h>
#include "ColorSet.h"
static ColorSet sDefaults = ColorSet::DefaultColorSet();
static std::map<color_which, BString> sColorNames = ColorSet::DefaultColorNames();
bool
match_rgb_color(rgb_color& color, uint8 red, uint8 green, uint8 blue)
static ColorDescription sColorDescriptionTable[] =
{
return color.red == red
&& color.green == green
&& color.blue == blue;
{ B_PANEL_BACKGROUND_COLOR, "Panel Background" },
{ B_PANEL_TEXT_COLOR, "Panel Text" },
{ B_DOCUMENT_BACKGROUND_COLOR, "Document Background" },
{ B_DOCUMENT_TEXT_COLOR, "Document Text" },
{ B_CONTROL_BACKGROUND_COLOR, "Control Background" },
{ B_CONTROL_TEXT_COLOR, "Control Text" },
{ B_CONTROL_BORDER_COLOR, "Control Border" },
{ B_CONTROL_HIGHLIGHT_COLOR, "Control Highlight" },
{ B_NAVIGATION_BASE_COLOR, "Navigation Base" },
{ B_NAVIGATION_PULSE_COLOR, "Navigation Pulse" },
{ B_SHINE_COLOR, "Shine" },
{ B_SHADOW_COLOR, "Shadow" },
{ B_MENU_BACKGROUND_COLOR, "Menu Background" },
{ B_MENU_SELECTED_BACKGROUND_COLOR, "Selected Menu Item Background" },
{ B_MENU_ITEM_TEXT_COLOR, "Menu Item Text" },
{ B_MENU_SELECTED_ITEM_TEXT_COLOR, "Selected Menu Item Text" },
{ B_MENU_SELECTED_BORDER_COLOR, "Selected Menu Item Border" },
{ B_TOOLTIP_BACKGROUND_COLOR, "Tooltip Background" },
{ B_TOOLTIP_TEXT_COLOR, "Tooltip Text" },
{ B_SUCCESS_COLOR, "Success" },
{ B_FAILURE_COLOR, "Failure" },
{ B_WINDOW_TAB_COLOR, "Window Tab" },
{ B_WINDOW_TEXT_COLOR, "Window Tab Text" },
{ B_WINDOW_INACTIVE_TAB_COLOR, "Inactive Window Tab" },
{ B_WINDOW_INACTIVE_TEXT_COLOR, "Inactive Window Tab Text" }
};
const int32 sColorDescriptionCount = sizeof(sColorDescriptionTable) / sizeof(ColorDescription);
const ColorDescription*
get_color_description(int32 index)
{
if (index < 0 || index >= sColorDescriptionCount)
return NULL;
return &sColorDescriptionTable[index];
}
int32
color_description_count(void)
{
return sColorDescriptionCount;
}
// #pragma mark -
@ -42,7 +76,7 @@ ColorSet::ColorSet()
*/
ColorSet::ColorSet(const ColorSet &cs)
{
SetColors(cs);
*this = cs;
}
/*!
@ -53,31 +87,10 @@ ColorSet::ColorSet(const ColorSet &cs)
ColorSet &
ColorSet::operator=(const ColorSet &cs)
{
SetColors(cs);
fColors = cs.fColors;
return *this;
}
/*!
\brief Copy function which handles assignments,
and, yes, *IT EVEN MAKES french fries!!*
\param cs Color set to copy from
*/
void
ColorSet::SetColors(const ColorSet &cs)
{
fColors = cs.fColors;
}
//! Prints all color set elements to stdout
void
ColorSet::PrintToStream(void) const
{
for (std::map<color_which, BString>::const_iterator it = sColorNames.begin(); it != sColorNames.end(); ++it) {
printf("%s ", it->second.String());
PrintMember(it->first);
printf("\n");
}
}
/*!
\brief Assigns the default system colors to the passed ColorSet object
@ -86,9 +99,6 @@ ColorSet::PrintToStream(void) const
ColorSet
ColorSet::DefaultColorSet(void)
{
#ifdef DEBUG_COLORSET
printf("Initializing color settings to defaults\n");
#endif
ColorSet set;
set.fColors[B_PANEL_BACKGROUND_COLOR] = make_color(216, 216, 216);
set.fColors[B_PANEL_TEXT_COLOR] = make_color(0, 0, 0);
@ -120,204 +130,22 @@ printf("Initializing color settings to defaults\n");
}
/*!
\brief Checks if the ColorSet can be set to defaults.
*/
bool
ColorSet::IsDefaultable()
{
return (*this == sDefaults);
}
/*!
\brief Attaches the color set's members as data to the given BMessage
\param msg The message to receive the attributes
*/
bool
ColorSet::ConvertToMessage(BMessage *msg) const
{
if(!msg)
return false;
msg->MakeEmpty();
rgb_color color;
for (std::map<color_which, BString>::const_iterator it = sColorNames.begin(); it != sColorNames.end(); ++it) {
std::map<color_which, rgb_color>::const_iterator cit = fColors.find(it->first);
if (cit != fColors.end())
msg->AddData(it->second.String(), (type_code)'RGBC', &(cit->second), sizeof(rgb_color));
else
msg->AddData(it->second.String(), (type_code)'RGBC', &color, sizeof(rgb_color));
}
return true;
}
/*!
\brief Assigns values to the color set's members based on values in the BMessage
\param msg The message containing the data for the color set's colors
*/
bool
ColorSet::ConvertFromMessage(const BMessage *msg)
{
if(!msg)
return false;
rgb_color *col;
ssize_t size;
BString str;
for (std::map<color_which, BString>::const_iterator it = sColorNames.begin();
it != sColorNames.end(); ++it) {
if (msg->FindData(it->second.String(),(type_code)'RGBC',(const void**)&col,&size)==B_OK)
fColors[it->first] = *col;
}
return true;
}
std::map<color_which, BString>
ColorSet::DefaultColorNames(void)
{
std::map<color_which, BString> names;
names[B_PANEL_BACKGROUND_COLOR] = "Panel Background";
names[B_PANEL_TEXT_COLOR] = "Panel Text";
names[B_DOCUMENT_BACKGROUND_COLOR] = "Document Background";
names[B_DOCUMENT_TEXT_COLOR] = "Document Text";
names[B_CONTROL_BACKGROUND_COLOR] = "Control Background";
names[B_CONTROL_TEXT_COLOR] = "Control Text";
names[B_CONTROL_BORDER_COLOR] = "Control Border";
names[B_CONTROL_HIGHLIGHT_COLOR] = "Control Highlight";
names[B_NAVIGATION_BASE_COLOR] = "Navigation Base";
names[B_NAVIGATION_PULSE_COLOR] = "Navigation Pulse";
names[B_SHINE_COLOR] = "Shine";
names[B_SHADOW_COLOR] = "Shadow";
names[B_MENU_BACKGROUND_COLOR] = "Menu Background";
names[B_MENU_SELECTED_BACKGROUND_COLOR] = "Selected Menu Item Background";
names[B_MENU_ITEM_TEXT_COLOR] = "Menu Item Text";
names[B_MENU_SELECTED_ITEM_TEXT_COLOR] = "Selected Menu Item Text";
names[B_MENU_SELECTED_BORDER_COLOR] = "Selected Menu Item Border";
names[B_TOOLTIP_BACKGROUND_COLOR] = "Tooltip Background";
names[B_TOOLTIP_TEXT_COLOR] = "Tooltip Text";
names[B_SUCCESS_COLOR] = "Success";
names[B_FAILURE_COLOR] = "Failure";
names[B_WINDOW_TAB_COLOR] = "Window Tab";
names[B_WINDOW_TEXT_COLOR] = "Window Tab Text";
names[B_WINDOW_INACTIVE_TAB_COLOR] = "Inactive Window Tab";
names[B_WINDOW_INACTIVE_TEXT_COLOR] = "Inactive Window Tab Text";
return names;
}
/*!
\brief Assigns a value to a named color member
\param string name of the color to receive the value
\param value An rgb_color which is the new value of the member
*/
status_t
void
ColorSet::SetColor(color_which which, rgb_color value)
{
fColors[which] = value;
return B_OK;
}
/*!
\brief Obtains the set's color member based on a specified string
\param string name of the color member to obtain
\return An RGBColor pointer or NULL if not found
*/
rgb_color
ColorSet::StringToColor(const char *string) const
{
rgb_color color;
color.set_to(0,0,0);
if (!string)
return color;
color_which which = StringToWhich(string);
if (which != -1) {
std::map<color_which, rgb_color>::const_iterator it = fColors.find(which);
if (it != fColors.end())
return it->second;
}
return color;
}
color_which
ColorSet::StringToWhich(const char *string) const
{
if(!string)
return (color_which)-1;
for (std::map<color_which, BString>::const_iterator it = sColorNames.begin(); it != sColorNames.end(); ++it)
if (it->second == string)
return it->first;
return (color_which)-1;
}
rgb_color
ColorSet::AttributeToColor(int32 which)
ColorSet::GetColor(int32 which)
{
return fColors[(color_which)which];
}
void
ColorSet::PrintMember(color_which which) const
{
std::map<color_which, rgb_color>::const_iterator it = fColors.find(which);
if (it != fColors.end())
printf("rgb_color(%d, %d, %d, %d)", it->second.red,it->second.green,it->second.blue,
it->second.alpha);
else
printf("color (%d) not found\n", which);
}
/*!
\brief Loads the saved system colors into a ColorSet
\param set the set to receive the system colors
\return B_OK if successful. See BFile for other error codes
*/
status_t
ColorSet::LoadColorSet(const char *path, ColorSet *set)
{
BFile file(path,B_READ_ONLY);
if (file.InitCheck()!=B_OK)
return file.InitCheck();
BMessage msg;
status_t status = msg.Unflatten(&file);
if (status != B_OK)
return status;
set->ConvertFromMessage(&msg);
return B_OK;
}
/*!
\brief Saves the saved system colors into a flattened BMessage
\param set ColorSet containing the colors to save
\return B_OK if successful. See BFile for other error codes
*/
status_t
ColorSet::SaveColorSet(const char *path, const ColorSet &set)
{
BFile file(path, B_READ_WRITE | B_ERASE_FILE | B_CREATE_FILE);
status_t status = file.InitCheck();
if (status != B_OK)
return status;
BMessage msg;
set.ConvertToMessage(&msg);
return msg.Flatten(&file);
}

View File

@ -17,6 +17,16 @@
#include <map>
typedef struct
{
color_which which;
const char* text;
} ColorDescription;
const ColorDescription* get_color_description(int32 index);
int32 color_description_count(void);
/*!
\class ColorSet ColorSet.h
\brief Encapsulates GUI system colors
@ -27,33 +37,22 @@ class ColorSet : public BLocker {
ColorSet(const ColorSet &cs);
ColorSet & operator=(const ColorSet &cs);
void SetColors(const ColorSet &cs);
void PrintToStream(void) const;
bool ConvertToMessage(BMessage *msg) const;
bool ConvertFromMessage(const BMessage *msg);
bool IsDefaultable(void);
rgb_color StringToColor(const char *string) const;
rgb_color AttributeToColor(int32 which);
status_t SetColor(color_which which, rgb_color value);
static status_t LoadColorSet(const char *path, ColorSet *set);
static status_t SaveColorSet(const char *path, const ColorSet &set);
rgb_color GetColor(int32 which);
void SetColor(color_which which, rgb_color value);
static ColorSet DefaultColorSet(void);
static std::map<color_which, BString> DefaultColorNames(void);
inline bool operator==(const ColorSet &other)
{
return (fColors == other.fColors);
return fColors == other.fColors;
}
inline bool operator!=(const ColorSet &other)
{
return fColors != other.fColors;
}
private:
color_which StringToWhich(const char *string) const;
void PrintMember(color_which which) const;
std::map<color_which, rgb_color> fColors;
};

View File

@ -9,160 +9,15 @@
#include "ColorWhichItem.h"
#include <stdio.h>
ColorWhichItem::ColorWhichItem(color_which which)
: BStringItem(NULL,0,false)
ColorWhichItem::ColorWhichItem(const char* text, color_which which)
: BStringItem(text, 0, false)
, colorWhich(which)
{
SetAttribute(which);
}
ColorWhichItem::~ColorWhichItem(void)
{
// Empty, but exists for just-in-case
}
void
ColorWhichItem::SetAttribute(color_which which)
{
switch(which) {
// cases not existing in R5 which exist in OpenBeOS
case B_PANEL_BACKGROUND_COLOR: {
attribute=which;
SetText("Panel Background");
break;
}
case B_PANEL_TEXT_COLOR: {
attribute=which;
SetText("Panel Text");
break;
}
case B_DOCUMENT_BACKGROUND_COLOR: {
attribute=which;
SetText("Document Background");
break;
}
case B_DOCUMENT_TEXT_COLOR: {
attribute=which;
SetText("Document Text");
break;
}
case B_CONTROL_BACKGROUND_COLOR: {
attribute=which;
SetText("Control Background");
break;
}
case B_CONTROL_TEXT_COLOR: {
attribute=which;
SetText("Control Text");
break;
}
case B_CONTROL_BORDER_COLOR: {
attribute=which;
SetText("Control Border");
break;
}
case B_CONTROL_HIGHLIGHT_COLOR: {
attribute=which;
SetText("Control Highlight");
break;
}
case B_TOOLTIP_BACKGROUND_COLOR: {
attribute=which;
SetText("Tooltip Background");
break;
}
case B_TOOLTIP_TEXT_COLOR: {
attribute=which;
SetText("Tooltip Text");
break;
}
case B_MENU_BACKGROUND_COLOR: {
attribute=which;
SetText("Menu Background");
break;
}
case B_MENU_SELECTION_BACKGROUND_COLOR: {
attribute=which;
SetText("Selected Menu Item Background");
break;
}
case B_MENU_ITEM_TEXT_COLOR: {
attribute=which;
SetText("Menu Item Text");
break;
}
case B_MENU_SELECTED_ITEM_TEXT_COLOR: {
attribute=which;
SetText("Selected Menu Item Text");
break;
}
case B_MENU_SELECTED_BORDER_COLOR: {
attribute=which;
SetText("Selected Menu Item Border");
break;
}
case B_NAVIGATION_BASE_COLOR: {
attribute=which;
SetText("Navigation Base");
break;
}
case B_NAVIGATION_PULSE_COLOR: {
attribute=which;
SetText("Navigation Pulse");
break;
}
case B_SUCCESS_COLOR: {
attribute=which;
SetText("Success");
break;
}
case B_FAILURE_COLOR: {
attribute=which;
SetText("Failure");
break;
}
case B_SHINE_COLOR: {
attribute=which;
SetText("Shine");
break;
}
case B_SHADOW_COLOR: {
attribute=which;
SetText("Shadow");
break;
}
case B_WINDOW_TAB_COLOR: {
attribute=which;
SetText("Window Tab");
break;
}
case B_WINDOW_TEXT_COLOR: {
attribute=which;
SetText("Window Text");
break;
}
case B_WINDOW_INACTIVE_TAB_COLOR: {
attribute=which;
SetText("Inactive Window Tab");
break;
}
case B_WINDOW_INACTIVE_TEXT_COLOR: {
attribute=which;
SetText("Inactive Window Tab Text");
break;
}
default: {
printf("unknown code '%c%c%c%c'\n",(char)((which & 0xFF000000) >> 24),
(char)((which & 0x00FF0000) >> 16),
(char)((which & 0x0000FF00) >> 8),
(char)((which & 0x000000FF)) );
break;
}
}
}
color_which
ColorWhichItem::GetAttribute(void)
ColorWhichItem::ColorWhich(void)
{
return attribute;
return colorWhich;
}

View File

@ -15,12 +15,12 @@
class ColorWhichItem : public BStringItem
{
public:
ColorWhichItem(color_which which);
~ColorWhichItem(void);
void SetAttribute(color_which which);
color_which GetAttribute(void);
ColorWhichItem(const char* text, color_which which);
color_which ColorWhich(void);
private:
color_which attribute;
color_which colorWhich;
};
#endif