[haiku-commits] haiku: hrev46580 - src/kits/interface headers/os/interface

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 22 Dec 2013 02:49:36 +0100 (CET)

hrev46580 adds 5 changesets to branch 'master'
old head: d3e73d457e74feb381f5984f060595a2a60e835d
new head: fe8787698c2a7ddc1f79d3bf645303ab7052e553
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=fe87876+%5Ed3e73d4

----------------------------------------------------------------------------

8719e0d: BControlLook: Add methods for getting insets
  
  * Update the previously unused frame_type and background_type enums.
  * Add methods GetFrameInsets(), GetBackgroundInsets(), GetInsets() to
    get the insets for a given frame type, background type, or both
    respectively.

1b848ee: BControlLook: Add DrawLabel() variants with icon
  
  A label, a bitmap, or both can be specified.

be26037: BControl: Add icon support
  
  The icon is meant as an addition to or replacement of the label. Icon
  bitmaps for various states of the control (off, on, partially on, each
  enabled or disabled, plus up to 125 custom states) can be set
  individually via SetIconBitmap() (getter IconBitmap()).
  The convenience method SetIcon() can be used to set the bitmaps for the
  standard states from a single bitmap; it also supports cropping the
  icon to its non-transparent area. Code borrowed from BIconButton.

be43674: BControl subclasses: Override SetIcon()
  
  ... and implement Perform() action for potential later use.

fe87876: BButton: Add icon support
  
  * Remove non-BControlLook drawing code. It's just an annoyance to
    maintain.
  * Update Draw() and _ValidatePreferredSize() to add icon support.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

22 files changed, 931 insertions(+), 315 deletions(-)
headers/os/interface/Button.h                    |   2 +
headers/os/interface/CheckBox.h                  |   2 +
headers/os/interface/ColorControl.h              |   2 +
headers/os/interface/Control.h                   |  59 ++-
headers/os/interface/ControlLook.h               |  37 +-
headers/os/interface/PictureButton.h             |   2 +
headers/os/interface/RadioButton.h               |   2 +
headers/os/interface/Slider.h                    |   2 +
headers/os/interface/TextControl.h               |   2 +
headers/private/binary_compatibility/Global.h    |   8 +-
headers/private/binary_compatibility/Interface.h |   6 +
headers/private/shared/IconButton.h              |   3 +-
src/kits/interface/Button.cpp                    | 322 +++---------
src/kits/interface/CheckBox.cpp                  |  12 +
src/kits/interface/ColorControl.cpp              |  12 +
src/kits/interface/Control.cpp                   | 507 ++++++++++++++++++-
src/kits/interface/ControlLook.cpp               | 215 ++++++--
src/kits/interface/PictureButton.cpp             |  12 +
src/kits/interface/RadioButton.cpp               |  11 +
src/kits/interface/Slider.cpp                    |  12 +
src/kits/interface/TextControl.cpp               |  14 +-
src/kits/shared/IconButton.cpp                   |   2 +-

############################################################################

Commit:      8719e0dc4bf8495cd70c2dc3d25a5165f7ea3d16
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8719e0d
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Dec 22 00:57:36 2013 UTC

BControlLook: Add methods for getting insets

* Update the previously unused frame_type and background_type enums.
* Add methods GetFrameInsets(), GetBackgroundInsets(), GetInsets() to
  get the insets for a given frame type, background type, or both
  respectively.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/ControlLook.h 
b/headers/os/interface/ControlLook.h
index 8039f14..3db12f7 100644
--- a/headers/os/interface/ControlLook.h
+++ b/headers/os/interface/ControlLook.h
@@ -35,16 +35,20 @@ public:
 
        enum frame_type {
                B_BUTTON_FRAME,
-               B_MENU_FRAME,
-               B_LISTVIEW_FRAME,
-               B_INPUT_FRAME
+               B_GROUP_FRAME,
+               B_MENU_FIELD_FRAME,
+               B_SCROLL_VIEW_FRAME,
+               B_TEXT_CONTROL_FRAME,
        };
 
        enum background_type {
                B_BUTTON_BACKGROUND,
                B_MENU_BACKGROUND,
-               B_LISTVIEW_BACKGROUND,
-               B_INPUT_BACKGROUND
+               B_MENU_BAR_BACKGROUND,
+               B_MENU_FIELD_BACKGROUND,
+               B_MENU_ITEM_BACKGROUND,
+               B_HORIZONTAL_SCROLL_BAR_BACKGROUND,
+               B_VERTICAL_SCROLL_BAR_BACKGROUND,
        };
 
        enum {
@@ -332,6 +336,18 @@ public:
                                                                        const 
rgb_color& base, uint32 flags,
                                                                        const 
BPoint& where);
 
+       virtual void                            GetFrameInsets(frame_type 
frameType,
+                                                                       uint32 
flags, float& _left, float& _top,
+                                                                       float& 
_right, float& _bottom);
+       virtual void                            GetBackgroundInsets(
+                                                                       
background_type backgroundType,
+                                                                       uint32 
flags, float& _left, float& _top,
+                                                                       float& 
_right, float& _bottom);
+                       void                            GetInsets(frame_type 
frameType,
+                                                                       
background_type backgroundType,
+                                                                       uint32 
flags, float& _left, float& _top,
+                                                                       float& 
_right, float& _bottom);
+
                        void                            SetBackgroundInfo(
                                                                        const 
BMessage& backgroundInfo);
 
diff --git a/src/kits/interface/ControlLook.cpp 
b/src/kits/interface/ControlLook.cpp
index baab42d..e4e0292 100644
--- a/src/kits/interface/ControlLook.cpp
+++ b/src/kits/interface/ControlLook.cpp
@@ -1902,6 +1902,86 @@ BControlLook::DrawLabel(BView* view, const char* label, 
const rgb_color& base,
 
 
 void
+BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
+       float& _top, float& _right, float& _bottom)
+{
+       // All frames have the same inset on each side.
+       float inset = 0;
+
+       switch (frameType) {
+               case B_BUTTON_FRAME:
+                       inset = (flags & B_DEFAULT_BUTTON) != 0 ? 6 : 3;
+                       break;
+               case B_GROUP_FRAME:
+               case B_MENU_FIELD_FRAME:
+                       inset = 3;
+                       break;
+               case B_SCROLL_VIEW_FRAME:
+               case B_TEXT_CONTROL_FRAME:
+                       inset = 2;
+                       break;
+       }
+
+       _left = inset;
+       _top = inset;
+       _right = inset;
+       _bottom = inset;
+}
+
+
+void
+BControlLook::GetBackgroundInsets(background_type backgroundType,
+       uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
+{
+       // Most backgrounds have the same inset on each side.
+       float inset = 0;
+
+       switch (backgroundType) {
+               case B_BUTTON_BACKGROUND:
+               case B_MENU_BACKGROUND:
+               case B_MENU_BAR_BACKGROUND:
+               case B_MENU_FIELD_BACKGROUND:
+               case B_MENU_ITEM_BACKGROUND:
+                       inset = 1;
+                       break;
+               case B_HORIZONTAL_SCROLL_BAR_BACKGROUND:
+                       _left = 2;
+                       _top = 0;
+                       _right = 1;
+                       _bottom = 0;
+                       return;
+               case B_VERTICAL_SCROLL_BAR_BACKGROUND:
+                       _left = 0;
+                       _top = 2;
+                       _right = 0;
+                       _bottom = 1;
+                       return;
+       }
+
+       _left = inset;
+       _top = inset;
+       _right = inset;
+       _bottom = inset;
+}
+
+
+void
+BControlLook::GetInsets(frame_type frameType, background_type backgroundType,
+       uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
+{
+       GetFrameInsets(frameType, flags, _left, _top, _right, _bottom);
+
+       float left, top, right, bottom;
+       GetBackgroundInsets(backgroundType, flags, left, top, right, bottom);
+
+       _left += left;
+       _top += top;
+       _right += right;
+       _bottom += bottom;
+}
+
+
+void
 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo)
 {
        fBackgroundInfo = backgroundInfo;

############################################################################

Commit:      1b848ee7f2943f00b95a8657494592e2d0f15898
URL:         http://cgit.haiku-os.org/haiku/commit/?id=1b848ee
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Dec 22 01:01:13 2013 UTC

BControlLook: Add DrawLabel() variants with icon

A label, a bitmap, or both can be specified.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/ControlLook.h 
b/headers/os/interface/ControlLook.h
index 3db12f7..8222ae2 100644
--- a/headers/os/interface/ControlLook.h
+++ b/headers/os/interface/ControlLook.h
@@ -12,6 +12,7 @@
 #include <Slider.h>
 
 
+class BBitmap;
 class BControl;
 class BGradientLinear;
 class BView;
@@ -336,6 +337,16 @@ public:
                                                                        const 
rgb_color& base, uint32 flags,
                                                                        const 
BPoint& where);
 
+                       void                            DrawLabel(BView* view, 
const char* label,
+                                                                       const 
BBitmap* icon, BRect rect,
+                                                                       const 
BRect& updateRect,
+                                                                       const 
rgb_color& base, uint32 flags);
+       virtual void                            DrawLabel(BView* view, const 
char* label,
+                                                                       const 
BBitmap* icon, BRect rect,
+                                                                       const 
BRect& updateRect,
+                                                                       const 
rgb_color& base, uint32 flags,
+                                                                       const 
BAlignment& alignment);
+
        virtual void                            GetFrameInsets(frame_type 
frameType,
                                                                        uint32 
flags, float& _left, float& _top,
                                                                        float& 
_right, float& _bottom);
diff --git a/src/kits/interface/ControlLook.cpp 
b/src/kits/interface/ControlLook.cpp
index e4e0292..6af7778 100644
--- a/src/kits/interface/ControlLook.cpp
+++ b/src/kits/interface/ControlLook.cpp
@@ -10,8 +10,11 @@
 
 #include <ControlLook.h>
 
+#include <algorithm>
+
 #include <Control.h>
 #include <GradientLinear.h>
+#include <LayoutUtils.h>
 #include <Region.h>
 #include <Shape.h>
 #include <String.h>
@@ -1730,7 +1733,7 @@ void
 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
        const BRect& updateRect, const rgb_color& base, uint32 flags)
 {
-       DrawLabel(view, label, rect, updateRect, base, flags,
+       DrawLabel(view, label, NULL, rect, updateRect, base, flags,
                DefaultLabelAlignment());
 }
 
@@ -1740,54 +1743,7 @@ BControlLook::DrawLabel(BView* view, const char* label, 
BRect rect,
        const BRect& updateRect, const rgb_color& base, uint32 flags,
        const BAlignment& alignment)
 {
-       if (!rect.Intersects(updateRect))
-               return;
-
-       // truncate the label if necessary and get the width and height
-       BString truncatedLabel(label);
-
-       BFont font;
-       view->GetFont(&font);
-
-       float width = rect.Width();
-       font.TruncateString(&truncatedLabel, B_TRUNCATE_END, width);
-       width = font.StringWidth(truncatedLabel.String());
-
-       font_height fontHeight;
-       font.GetHeight(&fontHeight);
-       float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
-
-       // handle alignment
-       BPoint location;
-
-       switch (alignment.horizontal) {
-       default:
-               case B_ALIGN_LEFT:
-                       location.x = rect.left;
-                       break;
-               case B_ALIGN_RIGHT:
-                       location.x = rect.right - width;
-                       break;
-               case B_ALIGN_CENTER:
-                       location.x = (rect.left + rect.right - width) / 2.0f;
-                       break;
-       }
-
-       switch (alignment.vertical) {
-               case B_ALIGN_TOP:
-                       location.y = rect.top + ceilf(fontHeight.ascent);
-                       break;
-               default:
-               case B_ALIGN_MIDDLE:
-                       location.y = floorf((rect.top + rect.bottom - height) / 
2.0f + 0.5f)
-                               + ceilf(fontHeight.ascent);
-                       break;
-               case B_ALIGN_BOTTOM:
-                       location.y = rect.bottom - ceilf(fontHeight.descent);
-                       break;
-       }
-
-       DrawLabel(view, truncatedLabel.String(), base, flags, location);
+       DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment);
 }
 
 
@@ -1902,6 +1858,87 @@ BControlLook::DrawLabel(BView* view, const char* label, 
const rgb_color& base,
 
 
 void
+BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
+       BRect rect, const BRect& updateRect, const rgb_color& base, uint32 
flags)
+{
+       DrawLabel(view, label, icon, rect, updateRect, base, flags,
+               DefaultLabelAlignment());
+}
+
+
+void
+BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
+       BRect rect, const BRect& updateRect, const rgb_color& base, uint32 
flags,
+       const BAlignment& alignment)
+{
+       if (!rect.Intersects(updateRect))
+               return;
+
+       if (label == NULL && icon == NULL)
+               return;
+
+       if (label == NULL) {
+               // icon only
+               BRect alignedRect = BLayoutUtils::AlignInFrame(rect,
+                       icon->Bounds().Size(), alignment);
+               drawing_mode oldMode = view->DrawingMode();
+               view->SetDrawingMode(B_OP_OVER);
+               view->DrawBitmap(icon, alignedRect.LeftTop());
+               view->SetDrawingMode(oldMode);
+               return;
+       }
+
+       // label, possibly with icon
+       float availableWidth = rect.Width();
+       float width = 0;
+       float textOffset = 0;
+       float height = 0;
+
+       if (icon != NULL) {
+               width = icon->Bounds().Width() + DefaultLabelSpacing() + 1;
+               height = icon->Bounds().Height() + 1;
+               textOffset = width;
+               availableWidth -= textOffset;
+       }
+
+       // truncate the label if necessary and get the width and height
+       BString truncatedLabel(label);
+
+       BFont font;
+       view->GetFont(&font);
+
+       font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth);
+       width += font.StringWidth(truncatedLabel.String());
+
+       font_height fontHeight;
+       font.GetHeight(&fontHeight);
+       float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
+       height = std::max(height, textHeight);
+
+       // handle alignment
+       BRect alignedRect = BLayoutUtils::AlignInFrame(rect,
+               BSize(width - 1, height - 1), alignment);
+
+       if (icon != NULL) {
+               BPoint location = alignedRect.LeftTop();
+               if (icon->Bounds().Height() + 1 < height)
+                       location.y += ceilf((height - icon->Bounds().Height() - 
1) / 2);
+
+               drawing_mode oldMode = view->DrawingMode();
+               view->SetDrawingMode(B_OP_OVER);
+               view->DrawBitmap(icon, location);
+               view->SetDrawingMode(oldMode);
+       }
+
+       BPoint location(alignedRect.left + textOffset,
+               alignedRect.top + ceilf(fontHeight.ascent));
+       if (textHeight < height)
+               location.y += ceilf((height - textHeight) / 2);
+       DrawLabel(view, truncatedLabel.String(), base, flags, location);
+}
+
+
+void
 BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
        float& _top, float& _right, float& _bottom)
 {

############################################################################

Commit:      be260374d58f6eae120320ac1ca1ba50783e8c4b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=be26037
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Dec 22 01:18:39 2013 UTC

BControl: Add icon support

The icon is meant as an addition to or replacement of the label. Icon
bitmaps for various states of the control (off, on, partially on, each
enabled or disabled, plus up to 125 custom states) can be set
individually via SetIconBitmap() (getter IconBitmap()).
The convenience method SetIcon() can be used to set the bitmaps for the
standard states from a single bitmap; it also supports cropping the
icon to its non-transparent area. Code borrowed from BIconButton.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/Control.h b/headers/os/interface/Control.h
index 31cd84f..0db157d 100644
--- a/headers/os/interface/Control.h
+++ b/headers/os/interface/Control.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2009, Haiku, Inc. All rights reserved.
+ * Copyright 2001-2013, Haiku, Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 #ifndef _CONTROL_H
@@ -16,11 +16,43 @@ enum {
        B_CONTROL_PARTIALLY_ON = 2
 };
 
+class BBitmap;
 class BWindow;
 
 
 class BControl : public BView, public BInvoker {
 public:
+                       // Values for [Set]IconBitmap(). Not all types are 
applicable for
+                       // all controls.
+                       enum {
+                               B_OFF_BITMAP                                    
= 0x00,
+                               B_ON_BITMAP                                     
        = 0x01,
+                               B_PARTIALLY_ON_BITMAP                   = 0x02,
+
+                               // flag, can be combined with any of the above
+                               B_DISABLED_BITMAP                               
= 0x80,
+                                       // disabled version of the specified 
bitmap
+                       };
+
+                       // flags for SetIconBitmap()
+                       enum {
+                               B_KEEP_BITMAP                                   
= 0x0001,
+                                       // transfer bitmap ownership to 
BControl object
+                       };
+
+                       // flags for SetIcon()
+                       enum {
+                               B_TRIM_BITMAP                                   
= 0x0100,
+                                       // crop the bitmap to the not fully 
transparent area, may
+                                       // change the icon size
+                               B_TRIM_BITMAP_KEEP_ASPECT               = 
0x0200,
+                                       // like B_TRIM_BITMAP, but keeps the 
aspect ratio
+                               B_CREATE_ON_BITMAP                              
= 0x0400,
+                               B_CREATE_PARTIALLY_ON_BITMAP    = 0x0800,
+                               B_CREATE_DISABLED_BITMAPS               = 
0x1000,
+                       };
+
+public:
                                                                BControl(BRect 
frame, const char* name,
                                                                        const 
char* label, BMessage* message,
                                                                        uint32 
resizingMode, uint32 flags);
@@ -70,6 +102,12 @@ public:
 
        virtual status_t                        Perform(perform_code d, void* 
arg);
 
+       virtual status_t                        SetIcon(const BBitmap* bitmap,
+                                                                       uint32 
flags = 0);
+                       status_t                        SetIconBitmap(const 
BBitmap* bitmap,
+                                                                       uint32 
which, uint32 flags = 0);
+                       const BBitmap*          IconBitmap(uint32 which) const;
+
 protected:
                        bool                            IsFocusChanging() const;
                        bool                            IsTracking() const;
@@ -78,7 +116,16 @@ protected:
                        void                            SetValueNoUpdate(int32 
value);
 
 private:
-       virtual void                            _ReservedControl1();
+                       struct IconData;
+
+private:
+       static  BBitmap*                        _ConvertToRGB32(const BBitmap* 
bitmap,
+                                                                       bool 
noAppServerLink = false);
+       static  status_t                        _TrimBitmap(const BBitmap* 
bitmap,
+                                                                       bool 
keepAspect, BBitmap*& _trimmedBitmap);
+                       status_t                        _MakeBitmaps(const 
BBitmap* bitmap,
+                                                                       uint32 
flags);
+
        virtual void                            _ReservedControl2();
        virtual void                            _ReservedControl3();
        virtual void                            _ReservedControl4();
@@ -87,14 +134,20 @@ private:
 
                        void                            InitData(BMessage* data 
= NULL);
 
+private:
                        char*                           fLabel;
                        int32                           fValue;
                        bool                            fEnabled;
                        bool                            fFocusChanging;
                        bool                            fTracking;
                        bool                            fWantsNav;
+                       IconData*                       fIconData;
 
-                       uint32                          _reserved[4];
+#ifdef B_HAIKU_64_BIT
+                       uint32                          _reserved[2];
+#else
+                       uint32                          _reserved[3];
+#endif
 };
 
 #endif // _CONTROL_H
diff --git a/headers/private/binary_compatibility/Global.h 
b/headers/private/binary_compatibility/Global.h
index 6ba9693..94e468d 100644
--- a/headers/private/binary_compatibility/Global.h
+++ b/headers/private/binary_compatibility/Global.h
@@ -29,12 +29,12 @@ enum {
        PERFORM_CODE_LAYOUT_INVALIDATED         = 1007,
        PERFORM_CODE_DO_LAYOUT                          = 1008,
        PERFORM_CODE_GET_TOOL_TIP_AT            = 1009,
+       PERFORM_CODE_LAYOUT_CHANGED                     = 1010,
+       PERFORM_CODE_SET_ICON                           = 1011,
 
        // support kit
-       PERFORM_CODE_ALL_ARCHIVED                       = 1010,
-       PERFORM_CODE_ALL_UNARCHIVED                     = 1011,
-
-       PERFORM_CODE_LAYOUT_CHANGED                     = 1012
+       PERFORM_CODE_ALL_ARCHIVED                       = 2000,
+       PERFORM_CODE_ALL_UNARCHIVED                     = 2001,
 };
 
 
diff --git a/headers/private/binary_compatibility/Interface.h 
b/headers/private/binary_compatibility/Interface.h
index 5653583..6255b5e 100644
--- a/headers/private/binary_compatibility/Interface.h
+++ b/headers/private/binary_compatibility/Interface.h
@@ -51,4 +51,10 @@ struct perform_data_get_tool_tip_at {
        bool            return_value;
 };
 
+struct perform_data_set_icon {
+       const BBitmap*  icon;
+       uint32                  flags;
+};
+
+
 #endif /* _BINARY_COMPATIBILITY_INTERFACE_H_ */
diff --git a/src/kits/interface/Control.cpp b/src/kits/interface/Control.cpp
index 8fd92bd..42dbc2f 100644
--- a/src/kits/interface/Control.cpp
+++ b/src/kits/interface/Control.cpp
@@ -1,9 +1,11 @@
 /*
- * Copyright 2001-2006, Haiku Inc.
+ * Copyright 2001-2013, Haiku, Inc.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
- *             Marc Flerackers (mflerackers@xxxxxxxxxx)
+ *             Marc Flerackers, mflerackers@xxxxxxxxxx
+ *             Stephan Aßmus, superstippi@xxxxxx
+ *             Ingo Weinhold, ingo_weinhold@xxxxxx
  */
 
 /*!    BControl is the base class for user-event handling objects. */
@@ -12,10 +14,13 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <Bitmap.h>
 #include <Control.h>
+#include <ObjectList.h>
 #include <PropertyInfo.h>
 #include <Window.h>
 
+#include <AutoDeleter.h>
 #include <binary_compatibility/Interface.h>
 
 
@@ -45,6 +50,85 @@ static property_info sPropertyList[] = {
 };
 
 
+struct BControl::IconData {
+public:
+       IconData()
+               :
+               fEnabledBitmaps(8, true),
+               fDisabledBitmaps(8, true)
+       {
+       }
+
+       ~IconData()
+       {
+               DeleteBitmaps();
+       }
+
+       BBitmap* CreateBitmap(const BRect& bounds, color_space colorSpace,
+               uint32 which)
+       {
+               BBitmap* bitmap = new(std::nothrow) BBitmap(bounds, colorSpace);
+               if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, 
which)) {
+                       delete bitmap;
+                       return NULL;
+               }
+
+               return bitmap;
+       }
+
+       BBitmap* CopyBitmap(const BBitmap& bitmapToClone, uint32 which)
+       {
+               BBitmap* bitmap = new(std::nothrow) BBitmap(bitmapToClone);
+               if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, 
which)) {
+                       delete bitmap;
+                       return NULL;
+               }
+
+               return bitmap;
+       }
+
+       bool SetBitmap(BBitmap* bitmap, uint32 which)
+       {
+               IconList& list = (which & B_DISABLED_BITMAP) == 0
+                       ? fEnabledBitmaps : fDisabledBitmaps;
+               which &= ~uint32(B_DISABLED_BITMAP);
+
+               int32 count = list.CountItems();
+               if ((int32)which < count) {
+                       list.ReplaceItem(which, bitmap);
+                       return true;
+               }
+
+               while (list.CountItems() < (int32)which) {
+                       if (!list.AddItem((BBitmap*)NULL))
+                               return false;
+               }
+
+               return list.AddItem(bitmap);
+       }
+
+       BBitmap* Bitmap(uint32 which) const
+       {
+               const IconList& list = (which & B_DISABLED_BITMAP) == 0
+                       ? fEnabledBitmaps : fDisabledBitmaps;
+               return list.ItemAt(which & ~uint32(B_DISABLED_BITMAP));
+       }
+
+       void DeleteBitmaps()
+       {
+               fEnabledBitmaps.MakeEmpty(true);
+               fDisabledBitmaps.MakeEmpty(true);
+       }
+
+private:
+       typedef BObjectList<BBitmap> IconList;
+
+private:
+       IconList        fEnabledBitmaps;
+       IconList        fDisabledBitmaps;
+};
+
+
 BControl::BControl(BRect frame, const char *name, const char *label,
        BMessage *message, uint32 resizingMode, uint32 flags)
        : BView(frame, name, resizingMode, flags)
@@ -70,6 +154,7 @@ BControl::BControl(const char *name, const char *label, 
BMessage *message,
 BControl::~BControl()
 {
        free(fLabel);
+       delete fIconData;
        SetMessage(NULL);
 }
 
@@ -509,12 +594,148 @@ BControl::Perform(perform_code code, void* _data)
                        BControl::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BControl::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BView::Perform(code, _data);
 }
 
 
+status_t
+BControl::SetIcon(const BBitmap* bitmap, uint32 flags)
+{
+       if (bitmap == NULL) {
+               delete fIconData;
+               fIconData = NULL;
+               return B_OK;
+       }
+
+       if (!bitmap->IsValid())
+               return B_BAD_VALUE;
+
+       // check the color space
+       bool hasAlpha = false;
+       bool canUseForMakeBitmaps = false;
+
+       switch (bitmap->ColorSpace()) {
+               case B_RGBA32:
+               case B_RGBA32_BIG:
+                       hasAlpha = true;
+                       // fall through
+               case B_RGB32:
+               case B_RGB32_BIG:
+                       canUseForMakeBitmaps = true;
+                       break;
+
+               case B_UVLA32:
+               case B_LABA32:
+               case B_HSIA32:
+               case B_HSVA32:
+               case B_HLSA32:
+               case B_CMYA32:
+               case B_RGBA15:
+               case B_RGBA15_BIG:
+               case B_CMAP8:
+                       hasAlpha = true;
+                       break;
+
+               default:
+                       break;
+       }
+
+       BBitmap* trimmedBitmap = NULL;
+
+       // trim the bitmap, if requested and the bitmap actually has alpha
+       status_t error;
+       if ((flags & (B_TRIM_BITMAP | B_TRIM_BITMAP_KEEP_ASPECT)) != 0
+               && hasAlpha) {
+               if (bitmap->ColorSpace() == B_RGBA32) {
+                       error = _TrimBitmap(bitmap,
+                               (flags & B_TRIM_BITMAP_KEEP_ASPECT) != 0, 
trimmedBitmap);
+               } else {
+                       BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true);
+                       if (rgb32Bitmap != NULL) {
+                               error = _TrimBitmap(rgb32Bitmap,
+                                       (flags & B_TRIM_BITMAP_KEEP_ASPECT) != 
0, trimmedBitmap);
+                               delete rgb32Bitmap;
+                       } else
+                               error = B_NO_MEMORY;
+               }
+
+               if (error != B_OK)
+                       return error;
+
+               bitmap = trimmedBitmap;
+               canUseForMakeBitmaps = true;
+       }
+
+       // create the bitmaps
+       if (canUseForMakeBitmaps) {
+               error = _MakeBitmaps(bitmap, flags);
+       } else {
+               if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true)) {
+                       error = _MakeBitmaps(rgb32Bitmap, flags);
+                       delete rgb32Bitmap;
+               } else
+                       error = B_NO_MEMORY;
+       }
+
+       delete trimmedBitmap;
+
+       InvalidateLayout();
+       Invalidate();
+
+       return error;
+}
+
+
+status_t
+BControl::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags)
+{
+       if (fIconData == NULL) {
+               fIconData = new(std::nothrow) IconData;
+               if (fIconData == NULL)
+                       return B_NO_MEMORY;
+       }
+
+       BBitmap* ourBitmap = NULL;
+       if (bitmap != NULL) {
+               if (!bitmap->IsValid())
+                       return B_BAD_VALUE;
+
+               if ((flags & B_KEEP_BITMAP) != 0) {
+                       ourBitmap = const_cast<BBitmap*>(bitmap);
+               } else {
+                       ourBitmap = _ConvertToRGB32(bitmap);
+                       if (ourBitmap == NULL)
+                               return B_NO_MEMORY;
+               }
+       }
+
+       if (!fIconData->SetBitmap(ourBitmap, which)) {
+               if (ourBitmap != bitmap)
+                       delete ourBitmap;
+               return B_NO_MEMORY;
+       }
+
+       InvalidateLayout();
+       Invalidate();
+
+       return B_OK;
+}
+       
+
+const BBitmap*
+BControl::IconBitmap(uint32 which) const
+{
+       return fIconData != NULL ? fIconData->Bitmap(which) : NULL;
+}
+
+
 bool
 BControl::IsFocusChanging() const
 {
@@ -536,7 +757,286 @@ BControl::SetTracking(bool state)
 }
 
 
-void BControl::_ReservedControl1() {}
+extern "C" status_t
+B_IF_GCC_2(_ReservedControl1__8BControl, _ZN8BControl17_ReservedControl1Ev)(
+       BControl* control, const BBitmap* icon, uint32 flags)
+{
+       // SetIcon()
+       perform_data_set_icon data;
+       data.icon = icon;
+       data.flags = flags;
+       return control->Perform(PERFORM_CODE_SET_ICON, &data);
+}
+
+
+/*static*/ BBitmap*
+BControl::_ConvertToRGB32(const BBitmap* bitmap, bool noAppServerLink)
+{
+       BBitmap* rgb32Bitmap = new(std::nothrow) BBitmap(bitmap->Bounds(),
+               noAppServerLink ? B_BITMAP_NO_SERVER_LINK : 0, B_RGBA32);
+       if (rgb32Bitmap == NULL)
+               return NULL;
+
+       if (!rgb32Bitmap->IsValid() || rgb32Bitmap->ImportBits(bitmap)!= B_OK) {
+               delete rgb32Bitmap;
+               return NULL;
+       }
+
+       return rgb32Bitmap;
+}
+
+
+/*static*/ status_t
+BControl::_TrimBitmap(const BBitmap* bitmap, bool keepAspect,
+       BBitmap*& _trimmedBitmap)
+{
+       if (bitmap == NULL || !bitmap->IsValid()
+               || bitmap->ColorSpace() != B_RGBA32) {
+               return B_BAD_VALUE;
+       }
+
+       uint8* bits = (uint8*)bitmap->Bits();
+       uint32 bpr = bitmap->BytesPerRow();
+       uint32 width = bitmap->Bounds().IntegerWidth() + 1;
+       uint32 height = bitmap->Bounds().IntegerHeight() + 1;
+       BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
+
+       for (uint32 y = 0; y < height; y++) {
+               uint8* b = bits + 3;
+               bool rowHasAlpha = false;
+               for (uint32 x = 0; x < width; x++) {
+                       if (*b) {
+                               rowHasAlpha = true;
+                               if (x < trimmed.left)
+                                       trimmed.left = x;
+                               if (x > trimmed.right)
+                                       trimmed.right = x;
+                       }
+                       b += 4;
+               }
+               if (rowHasAlpha) {
+                       if (y < trimmed.top)
+                               trimmed.top = y;
+                       if (y > trimmed.bottom)
+                               trimmed.bottom = y;
+               }
+               bits += bpr;
+       }
+
+       if (!trimmed.IsValid())
+               return B_BAD_VALUE;
+
+       if (keepAspect) {
+               float minInset = trimmed.left;
+               minInset = min_c(minInset, trimmed.top);
+               minInset = min_c(minInset, bitmap->Bounds().right - 
trimmed.right);
+               minInset = min_c(minInset, bitmap->Bounds().bottom - 
trimmed.bottom);
+               trimmed = bitmap->Bounds().InsetByCopy(minInset, minInset);
+       }
+       trimmed = trimmed & bitmap->Bounds();
+
+       BBitmap* trimmedBitmap = new(std::nothrow) BBitmap(
+               trimmed.OffsetToCopy(B_ORIGIN), B_BITMAP_NO_SERVER_LINK, 
B_RGBA32);
+       if (trimmedBitmap == NULL)
+               return B_NO_MEMORY;
+
+       bits = (uint8*)bitmap->Bits();
+       bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top;
+       uint8* dst = (uint8*)trimmedBitmap->Bits();
+       uint32 trimmedWidth = trimmedBitmap->Bounds().IntegerWidth() + 1;
+       uint32 trimmedHeight = trimmedBitmap->Bounds().IntegerHeight() + 1;
+       uint32 trimmedBPR = trimmedBitmap->BytesPerRow();
+       for (uint32 y = 0; y < trimmedHeight; y++) {
+               memcpy(dst, bits, trimmedWidth * 4);
+               dst += trimmedBPR;
+               bits += bpr;
+       }
+
+       _trimmedBitmap = trimmedBitmap;
+       return B_OK;
+}
+
+
+status_t
+BControl::_MakeBitmaps(const BBitmap* bitmap, uint32 flags)
+{
+       // make our own versions of the bitmap
+       BRect b(bitmap->Bounds());
+
+       IconData* iconData = new(std::nothrow) IconData;
+       if (iconData == NULL)
+               return B_NO_MEMORY;
+       ObjectDeleter<IconData> iconDataDeleter(iconData);
+
+       color_space format = bitmap->ColorSpace();
+       BBitmap* normalBitmap = iconData->CreateBitmap(b, format, B_OFF_BITMAP);
+       if (normalBitmap == NULL)
+               return B_NO_MEMORY;
+
+       BBitmap* disabledBitmap = NULL;
+       if ((flags & B_CREATE_DISABLED_BITMAPS) != 0) {
+               disabledBitmap = iconData->CreateBitmap(b, format,
+                       B_OFF_BITMAP | B_DISABLED_BITMAP);
+               if (disabledBitmap == NULL)
+                       return B_NO_MEMORY;
+       }
+
+       BBitmap* clickedBitmap = NULL;
+       if ((flags & (B_CREATE_ON_BITMAP | B_CREATE_PARTIALLY_ON_BITMAP)) != 0) 
{
+               clickedBitmap = iconData->CreateBitmap(b, format, B_ON_BITMAP);
+               if (clickedBitmap == NULL)
+                       return B_NO_MEMORY;
+       }
+
+       BBitmap* disabledClickedBitmap = NULL;
+       if (disabledBitmap != NULL && clickedBitmap != NULL) {
+               disabledClickedBitmap = iconData->CreateBitmap(b, format,
+                       B_ON_BITMAP | B_DISABLED_BITMAP);
+               if (disabledClickedBitmap == NULL)
+                       return B_NO_MEMORY;
+       }
+
+       // copy bitmaps from file bitmap
+       uint8* nBits = normalBitmap != NULL ? (uint8*)normalBitmap->Bits() : 
NULL;
+       uint8* dBits = disabledBitmap != NULL
+               ? (uint8*)disabledBitmap->Bits() : NULL;
+       uint8* cBits = clickedBitmap != NULL ? (uint8*)clickedBitmap->Bits() : 
NULL;
+       uint8* dcBits = disabledClickedBitmap != NULL
+               ? (uint8*)disabledClickedBitmap->Bits() : NULL;
+       uint8* fBits = (uint8*)bitmap->Bits();
+       int32 nbpr = normalBitmap->BytesPerRow();
+       int32 fbpr = bitmap->BytesPerRow();
+       int32 pixels = b.IntegerWidth() + 1;
+       int32 lines = b.IntegerHeight() + 1;
+       if (format == B_RGB32 || format == B_RGB32_BIG) {
+               // nontransparent version
+
+               // iterate over color components
+               for (int32 y = 0; y < lines; y++) {
+                       for (int32 x = 0; x < pixels; x++) {
+                               int32 nOffset = 4 * x;
+                               int32 fOffset = 4 * x;
+                               nBits[nOffset + 0] = fBits[fOffset + 0];
+                               nBits[nOffset + 1] = fBits[fOffset + 1];
+                               nBits[nOffset + 2] = fBits[fOffset + 2];
+                               nBits[nOffset + 3] = 255;
+
+                               // clicked bits are darker (lame method...)
+                               if (cBits != NULL) {
+                                       cBits[nOffset + 0] = 
uint8((float)nBits[nOffset + 0] * 0.8);
+                                       cBits[nOffset + 1] = 
uint8((float)nBits[nOffset + 1] * 0.8);
+                                       cBits[nOffset + 2] = 
uint8((float)nBits[nOffset + 2] * 0.8);
+                                       cBits[nOffset + 3] = 255;
+                               }
+
+                               // disabled bits have less contrast (lame 
method...)
+                               if (dBits != NULL) {
+                                       uint8 grey = 216;
+                                       float dist = (nBits[nOffset + 0] - 
grey) * 0.4;
+                                       dBits[nOffset + 0] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 1] - grey) * 
0.4;
+                                       dBits[nOffset + 1] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 2] - grey) * 
0.4;
+                                       dBits[nOffset + 2] = (uint8)(grey + 
dist);
+                                       dBits[nOffset + 3] = 255;
+                               }
+
+                               // disabled bits have less contrast (lame 
method...)
+                               if (dcBits != NULL) {
+                                       uint8 grey = 188;
+                                       float dist = (nBits[nOffset + 0] - 
grey) * 0.4;
+                                       dcBits[nOffset + 0] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 1] - grey) * 
0.4;
+                                       dcBits[nOffset + 1] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 2] - grey) * 
0.4;
+                                       dcBits[nOffset + 2] = (uint8)(grey + 
dist);
+                                       dcBits[nOffset + 3] = 255;
+                               }
+                       }
+                       fBits += fbpr;
+                       nBits += nbpr;
+                       if (cBits != NULL)
+                               cBits += nbpr;
+                       if (dBits != NULL)
+                               dBits += nbpr;
+                       if (dcBits != NULL)
+                               dcBits += nbpr;
+               }
+       } else if (format == B_RGBA32 || format == B_RGBA32_BIG) {
+               // transparent version
+
+               // iterate over color components
+               for (int32 y = 0; y < lines; y++) {
+                       for (int32 x = 0; x < pixels; x++) {
+                               int32 nOffset = 4 * x;
+                               int32 fOffset = 4 * x;
+                               nBits[nOffset + 0] = fBits[fOffset + 0];
+                               nBits[nOffset + 1] = fBits[fOffset + 1];
+                               nBits[nOffset + 2] = fBits[fOffset + 2];
+                               nBits[nOffset + 3] = fBits[fOffset + 3];
+
+                               // clicked bits are darker (lame method...)
+                               if (cBits != NULL) {
+                                       cBits[nOffset + 0] = 
(uint8)(nBits[nOffset + 0] * 0.8);
+                                       cBits[nOffset + 1] = 
(uint8)(nBits[nOffset + 1] * 0.8);
+                                       cBits[nOffset + 2] = 
(uint8)(nBits[nOffset + 2] * 0.8);
+                                       cBits[nOffset + 3] = fBits[fOffset + 3];
+                               }
+
+                               // disabled bits have less opacity
+                               if (dBits != NULL) {
+                                       uint8 grey = ((uint16)nBits[nOffset + 
0] * 10
+                                           + nBits[nOffset + 1] * 60
+                                               + nBits[nOffset + 2] * 30) / 
100;
+                                       float dist = (nBits[nOffset + 0] - 
grey) * 0.3;
+                                       dBits[nOffset + 0] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 1] - grey) * 
0.3;
+                                       dBits[nOffset + 1] = (uint8)(grey + 
dist);
+                                       dist = (nBits[nOffset + 2] - grey) * 
0.3;
+                                       dBits[nOffset + 2] = (uint8)(grey + 
dist);
+                                       dBits[nOffset + 3] = 
(uint8)(fBits[fOffset + 3] * 0.3);
+                               }
+
+                               // disabled bits have less contrast (lame 
method...)
+                               if (dcBits != NULL) {
+                                       dcBits[nOffset + 0] = 
(uint8)(dBits[nOffset + 0] * 0.8);
+                                       dcBits[nOffset + 1] = 
(uint8)(dBits[nOffset + 1] * 0.8);
+                                       dcBits[nOffset + 2] = 
(uint8)(dBits[nOffset + 2] * 0.8);
+                                       dcBits[nOffset + 3] = 
(uint8)(fBits[fOffset + 3] * 0.3);
+                               }
+                       }
+                       fBits += fbpr;
+                       nBits += nbpr;
+                       if (cBits != NULL)
+                               cBits += nbpr;
+                       if (dBits != NULL)
+                               dBits += nbpr;
+                       if (dcBits != NULL)
+                               dcBits += nbpr;
+               }
+       } else {
+               // unsupported format
+               return B_BAD_VALUE;
+       }
+
+       // make the partially-on bitmaps a copy of the on bitmaps
+       if ((flags & B_CREATE_PARTIALLY_ON_BITMAP) != 0) {
+               if (iconData->CopyBitmap(clickedBitmap, B_PARTIALLY_ON_BITMAP) 
== NULL)
+                       return B_NO_MEMORY;
+               if ((flags & B_CREATE_DISABLED_BITMAPS) != 0) {
+                       if (iconData->CopyBitmap(disabledClickedBitmap,
+                                       B_PARTIALLY_ON_BITMAP | 
B_DISABLED_BITMAP) == NULL) {
+                               return B_NO_MEMORY;
+                       }
+               }
+       }
+
+       delete fIconData;
+       fIconData = iconDataDeleter.Detach();
+       return B_OK;
+}
+
+
 void BControl::_ReservedControl2() {}
 void BControl::_ReservedControl3() {}
 void BControl::_ReservedControl4() {}
@@ -559,6 +1059,7 @@ BControl::InitData(BMessage *data)
        fFocusChanging = false;
        fTracking = false;
        fWantsNav = Flags() & B_NAVIGABLE;
+       fIconData = NULL;
 
        if (data && data->HasString("_fname"))
                SetFont(be_plain_font, B_FONT_FAMILY_AND_STYLE);

############################################################################

Commit:      be4367428b6478ae059614d7a9b6f6dc721e5dcb
URL:         http://cgit.haiku-os.org/haiku/commit/?id=be43674
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Dec 22 01:31:47 2013 UTC

BControl subclasses: Override SetIcon()

... and implement Perform() action for potential later use.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/Button.h b/headers/os/interface/Button.h
index 240b928..304bd64 100644
--- a/headers/os/interface/Button.h
+++ b/headers/os/interface/Button.h
@@ -68,6 +68,8 @@ public:
        virtual BSize                           MaxSize();
        virtual BSize                           PreferredSize();
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 
 protected:
        virtual void                            LayoutInvalidated(bool 
descendants = false);
diff --git a/headers/os/interface/CheckBox.h b/headers/os/interface/CheckBox.h
index 340bed2..70f89a8 100644
--- a/headers/os/interface/CheckBox.h
+++ b/headers/os/interface/CheckBox.h
@@ -69,6 +69,8 @@ public:
 
        virtual status_t                        Perform(perform_code code, 
void* data);
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
                        bool                            IsPartialStateToOff() 
const;
                        void                            
SetPartialStateToOff(bool partialToOff);
 
diff --git a/headers/os/interface/ColorControl.h 
b/headers/os/interface/ColorControl.h
index ca6171b..b686177 100644
--- a/headers/os/interface/ColorControl.h
+++ b/headers/os/interface/ColorControl.h
@@ -76,6 +76,8 @@ public:
        virtual void                            AllAttached();
        virtual void                            AllDetached();
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 private:
        virtual status_t                        Perform(perform_code d, void 
*arg);
                // this can be made public again if needed
diff --git a/headers/os/interface/PictureButton.h 
b/headers/os/interface/PictureButton.h
index 10cfa10..e457db8 100644
--- a/headers/os/interface/PictureButton.h
+++ b/headers/os/interface/PictureButton.h
@@ -79,6 +79,8 @@ public:
 
        virtual status_t                        Perform(perform_code code, 
void* data);
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 private:
        // FBC padding and forbidden methods
        virtual void                            _ReservedPictureButton1();
diff --git a/headers/os/interface/RadioButton.h 
b/headers/os/interface/RadioButton.h
index 48da018..040f6ee 100644
--- a/headers/os/interface/RadioButton.h
+++ b/headers/os/interface/RadioButton.h
@@ -63,6 +63,8 @@ public:
        virtual BSize                           MaxSize();
        virtual BAlignment                      LayoutAlignment();
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 private:
        friend  status_t                        _init_interface_kit_();
 
diff --git a/headers/os/interface/Slider.h b/headers/os/interface/Slider.h
index 8b76dfa..42e8148 100644
--- a/headers/os/interface/Slider.h
+++ b/headers/os/interface/Slider.h
@@ -159,6 +159,8 @@ public:
        virtual BSize                           MaxSize();
        virtual BSize                           PreferredSize();
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 protected:
        virtual void                            LayoutInvalidated(bool 
descendants);
 
diff --git a/headers/os/interface/TextControl.h 
b/headers/os/interface/TextControl.h
index 77d36d9..05bf6de 100644
--- a/headers/os/interface/TextControl.h
+++ b/headers/os/interface/TextControl.h
@@ -98,6 +98,8 @@ protected:
        virtual void                            LayoutInvalidated(bool 
descendants);
        virtual void                            DoLayout();
 
+       virtual status_t                        SetIcon(const BBitmap* icon, 
uint32 flags = 0);
+
 private:
        // FBC padding and forbidden methods
        virtual status_t                        Perform(perform_code d, void* 
arg);
diff --git a/headers/private/shared/IconButton.h 
b/headers/private/shared/IconButton.h
index 0b5a5f2..29f7535 100644
--- a/headers/private/shared/IconButton.h
+++ b/headers/private/shared/IconButton.h
@@ -71,7 +71,8 @@ public:
 
                        status_t                        SetIcon(int32 
resourceID);
                        status_t                        SetIcon(const char* 
pathToBitmap);
-                       status_t                        SetIcon(const BBitmap* 
bitmap);
+       virtual status_t                        SetIcon(const BBitmap* bitmap,
+                                                                       uint32 
flags = 0);
                        status_t                        SetIcon(const 
BMimeType* fileType,
                                                                        bool 
small = true);
                        status_t                        SetIcon(const unsigned 
char* bitsFromQuickRes,
diff --git a/src/kits/interface/Button.cpp b/src/kits/interface/Button.cpp
index 87f85a3..99364fa 100644
--- a/src/kits/interface/Button.cpp
+++ b/src/kits/interface/Button.cpp
@@ -661,6 +661,11 @@ BButton::Perform(perform_code code, void* _data)
                        BButton::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BButton::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
@@ -691,6 +696,13 @@ BButton::PreferredSize()
 }
 
 
+status_t
+BButton::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
 void
 BButton::LayoutInvalidated(bool descendants)
 {
diff --git a/src/kits/interface/CheckBox.cpp b/src/kits/interface/CheckBox.cpp
index 53a498a..d991bd0 100644
--- a/src/kits/interface/CheckBox.cpp
+++ b/src/kits/interface/CheckBox.cpp
@@ -589,12 +589,24 @@ BCheckBox::Perform(perform_code code, void* _data)
                        BCheckBox::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BCheckBox::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
 }
 
 
+status_t
+BCheckBox::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
 void
 BCheckBox::LayoutInvalidated(bool descendants)
 {
diff --git a/src/kits/interface/ColorControl.cpp 
b/src/kits/interface/ColorControl.cpp
index 1fbd4fc..245bb91 100644
--- a/src/kits/interface/ColorControl.cpp
+++ b/src/kits/interface/ColorControl.cpp
@@ -1037,6 +1037,13 @@ BColorControl::AllDetached()
 
 
 status_t
+BColorControl::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
+status_t
 BColorControl::Perform(perform_code code, void* _data)
 {
        switch (code) {
@@ -1086,6 +1093,11 @@ BColorControl::Perform(perform_code code, void* _data)
                        BColorControl::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BColorControl::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
diff --git a/src/kits/interface/PictureButton.cpp 
b/src/kits/interface/PictureButton.cpp
index 2b3b554..ee0c79f 100644
--- a/src/kits/interface/PictureButton.cpp
+++ b/src/kits/interface/PictureButton.cpp
@@ -470,12 +470,24 @@ BPictureButton::Perform(perform_code code, void* _data)
                        BPictureButton::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BPictureButton::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
 }
 
 
+status_t
+BPictureButton::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
 // #pragma mark -
 
 
diff --git a/src/kits/interface/RadioButton.cpp 
b/src/kits/interface/RadioButton.cpp
index 8918095..2230c49 100644
--- a/src/kits/interface/RadioButton.cpp
+++ b/src/kits/interface/RadioButton.cpp
@@ -555,6 +555,11 @@ BRadioButton::Perform(perform_code code, void* _data)
                        BRadioButton::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BRadioButton::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
@@ -580,6 +585,12 @@ BRadioButton::LayoutAlignment()
 }
 
 
+status_t
+BRadioButton::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
 
 void BRadioButton::_ReservedRadioButton1() {}
 void BRadioButton::_ReservedRadioButton2() {}
diff --git a/src/kits/interface/Slider.cpp b/src/kits/interface/Slider.cpp
index 6d654d8..1748594 100644
--- a/src/kits/interface/Slider.cpp
+++ b/src/kits/interface/Slider.cpp
@@ -345,6 +345,11 @@ BSlider::Perform(perform_code code, void* _data)
                        BSlider::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BSlider::SetIcon(data->icon, data->flags);
+               }
        }
 
        return BControl::Perform(code, _data);
@@ -1768,6 +1773,13 @@ BSlider::PreferredSize()
 }
 
 
+status_t
+BSlider::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
 void
 BSlider::LayoutInvalidated(bool descendants)
 {
diff --git a/src/kits/interface/TextControl.cpp 
b/src/kits/interface/TextControl.cpp
index ee77dec..9863ecd 100644
--- a/src/kits/interface/TextControl.cpp
+++ b/src/kits/interface/TextControl.cpp
@@ -947,6 +947,13 @@ BTextControl::DoLayout()
 }
 
 
+status_t
+BTextControl::SetIcon(const BBitmap* icon, uint32 flags)
+{
+       return BControl::SetIcon(icon, flags);
+}
+
+
 // #pragma mark -
 
 
@@ -981,7 +988,7 @@ BTextControl::Perform(perform_code code, void* _data)
                        BTextControl::GetHeightForWidth(data->width, 
&data->min, &data->max,
                                &data->preferred);
                        return B_OK;
-}
+               }
                case PERFORM_CODE_SET_LAYOUT:
                {
                        perform_data_set_layout* data = 
(perform_data_set_layout*)_data;
@@ -1000,6 +1007,11 @@ BTextControl::Perform(perform_code code, void* _data)
                        BTextControl::DoLayout();
                        return B_OK;
                }
+               case PERFORM_CODE_SET_ICON:
+               {
+                       perform_data_set_icon* data = 
(perform_data_set_icon*)_data;
+                       return BTextControl::SetIcon(data->icon, data->flags);
+               }
                case PERFORM_CODE_ALL_UNARCHIVED:
                {
                        perform_data_all_unarchived* data
diff --git a/src/kits/shared/IconButton.cpp b/src/kits/shared/IconButton.cpp
index fb55ff0..2bf8ea5 100644
--- a/src/kits/shared/IconButton.cpp
+++ b/src/kits/shared/IconButton.cpp
@@ -382,7 +382,7 @@ BIconButton::SetIcon(const char* pathToBitmap)
 
 
 status_t
-BIconButton::SetIcon(const BBitmap* bitmap)
+BIconButton::SetIcon(const BBitmap* bitmap, uint32 flags)
 {
        if (bitmap && bitmap->ColorSpace() == B_CMAP8) {
                status_t status = bitmap->InitCheck();

############################################################################

Revision:    hrev46580
Commit:      fe8787698c2a7ddc1f79d3bf645303ab7052e553
URL:         http://cgit.haiku-os.org/haiku/commit/?id=fe87876
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sun Dec 22 01:46:27 2013 UTC

BButton: Add icon support

* Remove non-BControlLook drawing code. It's just an annoyance to
  maintain.
* Update Draw() and _ValidatePreferredSize() to add icon support.

----------------------------------------------------------------------------

diff --git a/src/kits/interface/Button.cpp b/src/kits/interface/Button.cpp
index 99364fa..d8db09c 100644
--- a/src/kits/interface/Button.cpp
+++ b/src/kits/interface/Button.cpp
@@ -13,8 +13,10 @@
 
 #include <Button.h>
 
+#include <algorithm>
 #include <new>
 
+#include <Bitmap.h>
 #include <ControlLook.h>
 #include <Font.h>
 #include <LayoutUtils.h>
@@ -24,6 +26,9 @@
 #include <binary_compatibility/Interface.h>
 
 
+static const float kLabelMargin = 3;
+
+
 BButton::BButton(BRect frame, const char* name, const char* label,
                BMessage* message, uint32 resizingMode, uint32 flags)
        : BControl(frame, name, label, message, resizingMode,
@@ -103,246 +108,25 @@ BButton::Archive(BMessage* archive, bool deep) const
 void
 BButton::Draw(BRect updateRect)
 {
-       if (be_control_look != NULL) {
-               BRect rect(Bounds());
-               rgb_color background = LowColor();
-               rgb_color base = background;
-               uint32 flags = be_control_look->Flags(this);
-               if (IsDefault())
-                       flags |= BControlLook::B_DEFAULT_BUTTON;
-               be_control_look->DrawButtonFrame(this, rect, updateRect,
-                       base, background, flags);
-               be_control_look->DrawButtonBackground(this, rect, updateRect,
-                       base, flags);
-
-               // always leave some room around the label
-               rect.InsetBy(3.0, 3.0);
-               be_control_look->DrawLabel(this, Label(), rect, updateRect,
-                       base, flags, BAlignment(B_ALIGN_CENTER, 
B_ALIGN_MIDDLE));
-               return;
-       }
-
-       font_height fh;
-       GetFontHeight(&fh);
-
-       const BRect bounds = Bounds();
-       BRect rect = bounds;
-
-       const bool enabled = IsEnabled();
-       const bool pushed = Value() == B_CONTROL_ON;
-       // Default indicator
+       BRect rect(Bounds());
+       rgb_color background = LowColor();
+       rgb_color base = background;
+       uint32 flags = be_control_look->Flags(this);
        if (IsDefault())
-               rect = _DrawDefault(rect, enabled);
-
-       BRect fillArea = rect;
-       fillArea.InsetBy(3.0, 3.0);
-
-       BString text = Label();
-
-#if 1
-       // Label truncation
-       BFont font;
-       GetFont(&font);
-       font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width() - 4);
-#endif
-
-       // Label position
-       const float stringWidth = StringWidth(text.String());
-       const float x = (rect.right - stringWidth) / 2.0;
-       const float labelY = bounds.top
-               + ((bounds.Height() - fh.ascent - fh.descent) / 2.0)
-               + fh.ascent + 1.0;
-       const float focusLineY = labelY + fh.descent;
-
-       /* speed trick:
-          if the focus changes but the button is not pressed then we can
-          redraw only the focus line,
-          if the focus changes and the button is pressed invert the internal 
rect
-          this block takes care of all the focus changes
-       */
-       if (IsFocusChanging()) {
-               if (pushed) {
-                       rect.InsetBy(2.0, 2.0);
-                       InvertRect(rect);
-               } else {
-                       _DrawFocusLine(x, focusLineY, stringWidth, IsFocus()
-                               && Window()->IsActive());
-               }
-
-               return;
-       }
-
-       // colors
-       rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
-       rgb_color buttonBgColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
-       rgb_color lightColor;
-       rgb_color maxLightColor;
-
-       rgb_color dark1BorderColor;
-       rgb_color dark2BorderColor;
-
-       rgb_color bevelColor1;
-       rgb_color bevelColor2;
-       rgb_color bevelColorRBCorner;
-
-       rgb_color borderBevelShadow;
-       rgb_color borderBevelLight;
-
-       if (enabled) {
-               lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
-               maxLightColor = tint_color(panelBgColor, B_LIGHTEN_MAX_TINT);
+               flags |= BControlLook::B_DEFAULT_BUTTON;
+       be_control_look->DrawButtonFrame(this, rect, updateRect,
+               base, background, flags);
+       be_control_look->DrawButtonBackground(this, rect, updateRect,
+               base, flags);
 
-               dark1BorderColor = tint_color(panelBgColor, B_DARKEN_3_TINT);
-               dark2BorderColor = tint_color(panelBgColor, B_DARKEN_4_TINT);
+       // always leave some room around the label
+       rect.InsetBy(kLabelMargin, kLabelMargin);
 
-               bevelColor1 = tint_color(panelBgColor, B_DARKEN_2_TINT);
-               bevelColor2 = panelBgColor;
-
-               if (IsDefault()) {
-                       borderBevelShadow = tint_color(dark1BorderColor,
-                               (B_NO_TINT + B_DARKEN_1_TINT) / 2);
-                       borderBevelLight = tint_color(dark1BorderColor, 
B_LIGHTEN_1_TINT);
-
-                       borderBevelLight.red = (borderBevelLight.red + 
panelBgColor.red)
-                               / 2;
-                       borderBevelLight.green = (borderBevelLight.green
-                               + panelBgColor.green) / 2;
-                       borderBevelLight.blue = (borderBevelLight.blue
-                               + panelBgColor.blue) / 2;
-
-                       dark1BorderColor = tint_color(dark1BorderColor, 
B_DARKEN_3_TINT);
-                       dark2BorderColor = tint_color(dark1BorderColor, 
B_DARKEN_4_TINT);
-
-                       bevelColorRBCorner = borderBevelShadow;
-               } else {
-                       borderBevelShadow = tint_color(panelBgColor,
-                               (B_NO_TINT + B_DARKEN_1_TINT) / 2);
-                       borderBevelLight = buttonBgColor;
-
-                       bevelColorRBCorner = dark1BorderColor;
-               }
-       } else {
-               lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
-               maxLightColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
-
-               dark1BorderColor = tint_color(panelBgColor, B_DARKEN_1_TINT);
-               dark2BorderColor = tint_color(panelBgColor, B_DARKEN_2_TINT);
-
-               bevelColor1 = panelBgColor;
-               bevelColor2 = buttonBgColor;
-
-               if (IsDefault()) {
-                       borderBevelShadow = dark1BorderColor;
-                       borderBevelLight = panelBgColor;
-                       dark1BorderColor = tint_color(dark1BorderColor, 
B_DARKEN_1_TINT);
-                       dark2BorderColor = tint_color(dark1BorderColor, 1.16);
-
-               } else {
-                       borderBevelShadow = panelBgColor;
-                       borderBevelLight = panelBgColor;
-               }
-
-               bevelColorRBCorner = tint_color(panelBgColor, 1.08);;
-       }
-
-       // fill the button area
-       SetHighColor(buttonBgColor);
-       FillRect(fillArea);
-
-       BeginLineArray(22);
-       // bevel around external border
-       AddLine(BPoint(rect.left, rect.bottom),
-                       BPoint(rect.left, rect.top), borderBevelShadow);
-       AddLine(BPoint(rect.left + 1, rect.top),
-                       BPoint(rect.right, rect.top), borderBevelShadow);
-
-       AddLine(BPoint(rect.right, rect.top + 1),
-                       BPoint(rect.right, rect.bottom), borderBevelLight);
-       AddLine(BPoint(rect.left + 1, rect.bottom),
-                       BPoint(rect.right - 1, rect.bottom), borderBevelLight);
-
-       rect.InsetBy(1.0, 1.0);
-
-       // external border
-       AddLine(BPoint(rect.left, rect.bottom),
-                       BPoint(rect.left, rect.top), dark1BorderColor);
-       AddLine(BPoint(rect.left + 1, rect.top),
-                       BPoint(rect.right, rect.top), dark1BorderColor);
-       AddLine(BPoint(rect.right, rect.top + 1),
-                       BPoint(rect.right, rect.bottom), dark2BorderColor);
-       AddLine(BPoint(rect.right - 1, rect.bottom),
-                       BPoint(rect.left + 1, rect.bottom), dark2BorderColor);
-
-       rect.InsetBy(1.0, 1.0);
-
-       // Light
-       AddLine(BPoint(rect.left, rect.top),
-                       BPoint(rect.left, rect.top), buttonBgColor);
-       AddLine(BPoint(rect.left, rect.top + 1),
-                       BPoint(rect.left, rect.bottom - 1), lightColor);
-       AddLine(BPoint(rect.left, rect.bottom),
-                       BPoint(rect.left, rect.bottom), bevelColor2);
-       AddLine(BPoint(rect.left + 1, rect.top),
-                       BPoint(rect.right - 1, rect.top), lightColor);
-       AddLine(BPoint(rect.right, rect.top),
-                       BPoint(rect.right, rect.top), bevelColor2);
-       // Shadow
-       AddLine(BPoint(rect.left + 1, rect.bottom),
-                       BPoint(rect.right - 1, rect.bottom), bevelColor1);
-       AddLine(BPoint(rect.right, rect.bottom),
-                       BPoint(rect.right, rect.bottom), bevelColorRBCorner);
-       AddLine(BPoint(rect.right, rect.bottom - 1),
-                       BPoint(rect.right, rect.top + 1), bevelColor1);
-
-       rect.InsetBy(1.0, 1.0);
-
-       // Light
-       AddLine(BPoint(rect.left, rect.top),
-                       BPoint(rect.left, rect.bottom - 1), maxLightColor);
-       AddLine(BPoint(rect.left, rect.bottom),
-                       BPoint(rect.left, rect.bottom), buttonBgColor);
-       AddLine(BPoint(rect.left + 1, rect.top),
-                       BPoint(rect.right - 1, rect.top), maxLightColor);
-       AddLine(BPoint(rect.right, rect.top),
-                       BPoint(rect.right, rect.top), buttonBgColor);
-       // Shadow
-       AddLine(BPoint(rect.left + 1, rect.bottom),
-                       BPoint(rect.right, rect.bottom), bevelColor2);
-       AddLine(BPoint(rect.right, rect.bottom - 1),
-                       BPoint(rect.right, rect.top + 1), bevelColor2);
-
-       rect.InsetBy(1.0,1.0);
-
-       EndLineArray();
-
-       // Invert if clicked
-       if (enabled && pushed) {
-               rect.InsetBy(-2.0, -2.0);
-               InvertRect(rect);
-       }
-
-       // Label color
-       if (enabled) {
-               if (pushed) {
-                       SetHighColor(maxLightColor);
-                       SetLowColor(255 - buttonBgColor.red,
-                                               255 - buttonBgColor.green,
-                                               255 - buttonBgColor.blue);
-               } else {
-                       SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
-                       SetLowColor(buttonBgColor);
-               }
-       } else {
-               SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT));
-               SetLowColor(buttonBgColor);
-       }
-
-       // Draw the label
-       DrawString(text.String(), BPoint(x, labelY));
-
-       // Focus line
-       if (enabled && IsFocus() && Window()->IsActive() && !pushed)
-               _DrawFocusLine(x, focusLineY, stringWidth, true);
+       const BBitmap* icon = IconBitmap(
+               (Value() == B_CONTROL_OFF ? B_OFF_BITMAP : B_ON_BITMAP)
+                       | (IsEnabled() ? 0 : B_DISABLED_BITMAP));
+       be_control_look->DrawLabel(this, Label(), icon, rect, updateRect,
+               base, flags, BAlignment(B_ALIGN_CENTER, B_ALIGN_MIDDLE));
 }
 
 
@@ -699,7 +483,8 @@ BButton::PreferredSize()
 status_t
 BButton::SetIcon(const BBitmap* icon, uint32 flags)
 {
-       return BControl::SetIcon(icon, flags);
+       return BControl::SetIcon(icon,
+               flags | B_CREATE_ON_BITMAP | B_CREATE_DISABLED_BITMAPS);
 }
 
 
@@ -727,23 +512,52 @@ BSize
 BButton::_ValidatePreferredSize()
 {
        if (fPreferredSize.width < 0) {
+               float left, top, right, bottom;
+               be_control_look->GetInsets(BControlLook::B_BUTTON_FRAME,
+                       BControlLook::B_BUTTON_BACKGROUND,
+                       fDrawAsDefault ? BControlLook::B_DEFAULT_BUTTON : 0,
+                       left, top, right, bottom);
+
                // width
-               float width = 20.0f + (float)ceil(StringWidth(Label()));
-               if (width < 75.0f)
-                       width = 75.0f;
+               float width = left + right + 2 * kLabelMargin - 1;
 
-               if (fDrawAsDefault)
-                       width += 6.0f;
+               const char* label = Label();
+               if (label != NULL) {
+                       width = std::max(width, 20.0f);
+                       width += (float)ceil(StringWidth(label));
+               }
 
-               fPreferredSize.width = width;
+               const BBitmap* icon = IconBitmap(B_OFF_BITMAP);
+               if (icon != NULL)
+                       width += icon->Bounds().Width() + 1;
+
+               if (label != NULL && icon != NULL)
+                       width += be_control_look->DefaultLabelSpacing();
 
                // height
-               font_height fontHeight;
-               GetFontHeight(&fontHeight);
+               float minHorizontalMargins = top + bottom + 2 * kLabelMargin;
+               float height = -1;
+
+               if (label != NULL) {
+                       font_height fontHeight;
+                       GetFontHeight(&fontHeight);
+                       float textHeight = fontHeight.ascent + 
fontHeight.descent;
+                       height = ceilf(textHeight * 1.8);
+                       float margins = height - ceilf(textHeight);
+                       if (margins < minHorizontalMargins)
+                               height += minHorizontalMargins - margins;
+               }
+
+               if (icon != NULL) {
+                       height = std::max(height,
+                               icon->Bounds().Height() + minHorizontalMargins);
+               }
+
+               // force some minimum width/height values
+               width = std::max(width, label != NULL ? 75.0f : 5.0f);
+               height = std::max(height, 5.0f);
 
-               fPreferredSize.height
-                       = ceilf((fontHeight.ascent + fontHeight.descent) * 1.8)
-                               + (fDrawAsDefault ? 6.0f : 0);
+               fPreferredSize.Set(width, height);
 
                ResetLayoutInvalidation();
        }


Other related posts:

  • » [haiku-commits] haiku: hrev46580 - src/kits/interface headers/os/interface - ingo_weinhold