← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2573: rework the tab icon cache to clean up unused icons

 

------------------------------------------------------------
revno: 2573
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Mon 2011-06-27 20:46:47 +0200
message:
  rework the tab icon cache to clean up unused icons
modified:
  dwt/include/dwt/widgets/Frame.h
  dwt/include/dwt/widgets/TabView.h
  dwt/src/widgets/TabView.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dwt/include/dwt/widgets/Frame.h'
--- dwt/include/dwt/widgets/Frame.h	2011-04-19 20:04:13 +0000
+++ dwt/include/dwt/widgets/Frame.h	2011-06-27 18:46:47 +0000
@@ -155,12 +155,12 @@
 
 inline void Frame::setSmallIcon(const IconPtr& icon) {
 	smallIcon = icon;
-	sendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(smallIcon->handle()));
+	sendMessage(WM_SETICON, ICON_SMALL, smallIcon ? reinterpret_cast<LPARAM>(smallIcon->handle()) : 0);
 }
 
 inline void Frame::setLargeIcon(const IconPtr& icon) {
 	largeIcon = icon;
-	sendMessage(WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(largeIcon->handle()));
+	sendMessage(WM_SETICON, ICON_BIG, largeIcon ? reinterpret_cast<LPARAM>(largeIcon->handle()) : 0);
 }
 
 inline Frame::Frame(Widget * parent, Dispatcher& dispatcher) :

=== modified file 'dwt/include/dwt/widgets/TabView.h'
--- dwt/include/dwt/widgets/TabView.h	2011-06-01 19:02:45 +0000
+++ dwt/include/dwt/widgets/TabView.h	2011-06-27 18:46:47 +0000
@@ -150,9 +150,12 @@
 		TabView* control; // for painting messages
 		ContainerPtr w;
 		tstring text;
+		IconPtr icon;
 		ContextMenuFunction handleContextMenu;
 		bool marked;
-		TabInfo(TabView* control_, ContainerPtr w_) : control(control_), w(w_), handleContextMenu(0), marked(false) { }
+
+		TabInfo(TabView* control, ContainerPtr w, IconPtr icon) :
+		control(control), w(w), icon(icon), handleContextMenu(0), marked(false) { }
 	};
 
 	Theme theme;
@@ -176,8 +179,7 @@
 	typedef WindowList::iterator WindowIter;
 	WindowList viewOrder;
 	Rectangle clientSize;
-	ImageListPtr imageList;
-	std::vector<IconPtr> icons;
+	ImageListPtr icons;
 	int active;
 	ContainerPtr dragging;
 	tstring tipText;
@@ -208,10 +210,14 @@
 	tstring formatTitle(tstring title);
 	void layout();
 
+	/** @internal add an icon to the icon cache.
+	@param icon must be a valid icon.
+	@return the index of the icon in the icon cache. */
 	int addIcon(const IconPtr& icon);
+	int getImage(unsigned index);
+	void removeIcon(unsigned index);
 	void swapWidgets(ContainerPtr oldW, ContainerPtr newW);
 
-	IconPtr getIcon(unsigned index) const;
 	void setText(unsigned idx, const tstring& text);
 	void redraw(unsigned index);
 	void draw(Canvas& canvas, unsigned index, Rectangle&& rect, bool isSelected);
@@ -231,8 +237,6 @@
 	// AspectSelection expectation implementation
 	static Message getSelectionChangedMessage();
 
-	const ImageListPtr& getImageList() const;
-
 	int hitTest(const ScreenCoordinate& pt);
 
 	/// Get the area not used by the tabs

=== modified file 'dwt/src/widgets/TabView.cpp'
--- dwt/src/widgets/TabView.cpp	2011-06-01 19:02:45 +0000
+++ dwt/src/widgets/TabView.cpp	2011-06-27 18:46:47 +0000
@@ -126,9 +126,8 @@
 		setFont(font);
 	}
 
-	imageList = new ImageList(Point(16, 16));
-
-	TabCtrl_SetImageList(handle(), imageList->handle());
+	icons = new ImageList(Point(16, 16));
+	TabCtrl_SetImageList(handle(), icons->handle());
 
 	onSelectionChanged([this] { handleTabSelected(); });
 	onLeftMouseDown([this](const MouseEvent& me) { return handleLeftMouseDown(me); });
@@ -145,12 +144,10 @@
 }
 
 void TabView::add(ContainerPtr w, const IconPtr& icon) {
-	int image = addIcon(icon);
-
-	size_t tabs = size();
-
-	TabInfo* ti = new TabInfo(this, w);
-	TCITEM item = {  TCIF_PARAM };
+	const size_t pos = size();
+
+	TabInfo* ti = new TabInfo(this, w, icon);
+	TCITEM item = { TCIF_PARAM };
 	item.lParam = reinterpret_cast<LPARAM>(ti);
 
 	if(!hasStyle(TCS_OWNERDRAWFIXED)) {
@@ -159,19 +156,19 @@
 		item.pszText = const_cast<LPTSTR>(ti->text.c_str());
 	}
 
-	if(image != -1) {
+	if(icon) {
 		item.mask |= TCIF_IMAGE;
-		item.iImage = image;
+		item.iImage = addIcon(icon);
 	}
 
-	int newIdx = TabCtrl_InsertItem( handle(), tabs, &item );
+	int newIdx = TabCtrl_InsertItem(handle(), pos, &item);
 	if ( newIdx == - 1 ) {
 		throw Win32Exception("Error while trying to add page into Tab Sheet");
 	}
 
 	if(taskbar) {
 		addToTaskbar(w);
-		if(image != -1) {
+		if(icon) {
 			setTaskbarIcon(w, icon);
 		}
 	}
@@ -184,7 +181,7 @@
 		} else {
 			swapWidgets(0, w);
 		}
-		setActive(tabs);
+		setActive(pos);
 	}
 
 	layout();
@@ -198,7 +195,7 @@
 }
 
 void TabView::remove(ContainerPtr w) {
-	int i = findTab(w);
+	auto i = findTab(w);
 	if(i == -1) {
 		return;
 	}
@@ -214,6 +211,8 @@
 	if(w == dragging)
 		dragging = 0;
 
+	removeIcon(i);
+
 	delete getTabInfo(i);
 	erase(i);
 
@@ -234,37 +233,29 @@
 	}
 }
 
-IconPtr TabView::getIcon(unsigned index) const {
-	TCITEM item = { TCIF_IMAGE };
-	TabCtrl_GetItem(handle(), index, &item);
-	if(item.iImage >= 0 && item.iImage < imageList->size())
-		return imageList->getIcon(item.iImage);
-	return IconPtr();
+IconPtr TabView::getIcon(ContainerPtr w) const {
+	auto ti = getTabInfo(w);
+	return ti ? ti->icon : 0;
 }
 
 void TabView::setIcon(ContainerPtr w, const IconPtr& icon) {
-	int i = findTab(w);
-	if(i != -1) {
-		int image = addIcon(icon);
-		if(image != -1) {
-			TCITEM item = { TCIF_IMAGE };
-			item.iImage = image;
-			TabCtrl_SetItem(this->handle(), i, &item);
-
-			if(taskbar) {
-				setTaskbarIcon(w, icon);
-			}
+	auto i = findTab(w);
+	auto ti = getTabInfo(i);
+	if(ti) {
+		removeIcon(i);
+
+		ti->icon = icon;
+
+		TCITEM item = { TCIF_IMAGE };
+		item.iImage = icon ? addIcon(icon) : -1;
+		TabCtrl_SetItem(handle(), i, &item);
+
+		if(taskbar) {
+			setTaskbarIcon(w, icon);
 		}
 	}
 }
 
-IconPtr TabView::getIcon(ContainerPtr w) const {
-	int i = findTab(w);
-	if(i != -1)
-		return getIcon(i);
-	return IconPtr();
-}
-
 void TabView::onTabContextMenu(ContainerPtr w, const ContextMenuFunction& f) {
 	TabInfo* ti = getTabInfo(w);
 	if(ti) {
@@ -368,8 +359,9 @@
 TabView::TabInfo* TabView::getTabInfo(int i) const {
 	if(i != -1) {
 		TCITEM item = { TCIF_PARAM };
-		TabCtrl_GetItem(handle(), i, &item);
-		return reinterpret_cast<TabInfo*>(item.lParam);
+		if(TabCtrl_GetItem(handle(), i, &item)) {
+			return reinterpret_cast<TabInfo*>(item.lParam);
+		}
 	}
 	return 0;
 }
@@ -468,21 +460,50 @@
 }
 
 int TabView::addIcon(const IconPtr& icon) {
-	int image = -1;
-	if(icon) {
-		for(size_t i = 0; i < icons.size(); ++i) {
-			if(*icon == *icons[i]) {
-				image = i;
-				break;
+	// see if one of the current tabs already has the icon; in that case, reuse it.
+	for(size_t i = 0, n = size(); i < n; ++i) {
+		auto ti = getTabInfo(i);
+		if(ti && ti->icon && *ti->icon == *icon) {
+			auto image = getImage(i);
+			if(image != -1) {
+				return image;
 			}
 		}
-		if(image == -1) {
-			image = icons.size();
-			icons.push_back(icon);
-			getImageList()->add(*icon);
-		}
-	}
-	return image;
+	}
+
+	auto ret = icons->size();
+	icons->add(*icon);
+	return ret;
+}
+
+int TabView::getImage(unsigned index) {
+	TCITEM item = { TCIF_IMAGE };
+	if(TabCtrl_GetItem(handle(), index, &item)) {
+		return item.iImage;
+	}
+	return -1;
+}
+
+void TabView::removeIcon(unsigned index) {
+	auto t = getTabInfo(index);
+	if(!t || !t->icon)
+		return;
+
+	// make sure no other tab is still using this icon.
+	for(size_t i = 0, n = size(); i < n; ++i) {
+		if(i == index) {
+			continue;
+		}
+		auto ti = getTabInfo(i);
+		if(ti && ti->icon && *ti->icon == *t->icon) {
+			return;
+		}
+	}
+
+	auto image = getImage(index);
+	if(image != -1) {
+		TabCtrl_RemoveImage(handle(), image);
+	}
 }
 
 LRESULT TabView::handleToolTip(LPARAM lParam) {
@@ -724,13 +745,12 @@
 	rect.pos += margin;
 	rect.size -= margin + margin;
 
-	IconPtr icon = getIcon(index);
-	if(icon) {
-		Point size = icon->getSize();
+	if(ti->icon) {
+		Point size = ti->icon->getSize();
 		Point pos = rect.pos;
 		if(size.y < rect.size.y)
 			pos.y += (rect.size.y - size.y) / 2; // center the icon vertically
-		canvas.drawIcon(icon, Rectangle(pos, size));
+		canvas.drawIcon(ti->icon, Rectangle(pos, size));
 
 		size.x += margin.x;
 		rect.pos.x += size.x;
@@ -876,10 +896,6 @@
 	return rect;
 }
 
-const ImageListPtr& TabView::getImageList() const {
-	return imageList;
-}
-
 int TabView::hitTest(const ScreenCoordinate& pt) {
 	TCHITTESTINFO tci = { ClientCoordinate(pt, this).getPoint() };
 	return TabCtrl_HitTest(handle(), &tci);