1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
|
/*
* astyle --force-indent=tab=4 --brackets=linux --indent-switches
* --pad=oper --one-line=keep-blocks --unpad=paren
*
* Miranda NG: the free IM client for Microsoft* Windows*
*
* Copyright 2000-2009 Miranda ICQ/IM project,
* all portions of this codebase are copyrighted to the people
* listed in contributors.txt.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* you should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* part of tabSRMM messaging plugin for Miranda.
*
* (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
*
* the contact switch bar on the left (or right) side
*
*/
#ifndef __SIDEBAR_H
#define __SIDEBAR_H
struct TSideBarNotify
{
NMHDR nmHdr;
const TWindowData* dat;
};
/* layout description structure */
struct TSideBarLayout
{
TCHAR szName[50]; // everything wants a name...
LONG width; // width of the switchbar element (a single button)
LONG height; // height of a single switchbar element
DWORD dwFlags; // flags, obviously :)
/*
* the following 4 items define pointers to the actual renderer functions for that sidebar layout
* a default is always provided, however, it has been designed to be easily extendible without
* rewriting lots of code just in order to change how the switchbar items look like.
*/
void (__fastcall *pfnContentRenderer)(const HDC hdc, const RECT *rc, const CSideBarButton *item);
void (__fastcall *pfnBackgroundRenderer)(const HDC hdc, const RECT *rc, const CSideBarButton *item);
const SIZE& (__fastcall *pfnMeasureItem)(CSideBarButton *item);
void (__fastcall *pfnLayout)(const CSideBar *sideBar, RECT *rc);
UINT uId; // numeric id by which the layout is identified. basically, the index into the array.
};
class CSideBar;
class CSideBarButton
{
public:
CSideBarButton(const UINT id, CSideBar *sideBar);
CSideBarButton(const TWindowData *dat, CSideBar *sideBar);
~CSideBarButton();
LONG getHeight() const { return(m_sz.cy); }
const SIZE& getSize() const { return(m_sz); }
void setSize(const SIZE& newSize) { m_sz = newSize; }
const bool isTopAligned() const { return(m_isTopAligned); }
const HWND getHwnd() const { return(m_hwnd); }
const UINT getID() const { return(m_id); }
const HANDLE getContactHandle() const { return(m_dat->hContact); }
const TWindowData* getDat() const { return(m_dat); }
const TSideBarLayout* getLayout() const { return(m_sideBarLayout); }
void RenderThis(const HDC hdc) const;
void renderIconAndNick(const HDC hdc, const RECT *rcItem) const;
int testCloseButton() const;
void Show(const int showCmd) const;
void activateSession() const;
const SIZE& measureItem();
void setLayout(const TSideBarLayout *newLayout);
void invokeContextMenu();
public:
CSideBar* m_sideBar;
const TSButtonCtrl* m_buttonControl; // private data struct of the Win32 button object
private:
void _create();
private:
const TSideBarLayout* m_sideBarLayout;
HWND m_hwnd; // window handle for the TSButton object
const TWindowData* m_dat; // session data
UINT m_id; // control id
bool m_isTopAligned;
SIZE m_sz;
};
class CSideBar
{
public:
enum {
NR_LAYOUTS = 4
};
enum {
/* layout ids. index into m_layouts[] */
SIDEBARLAYOUT_VERTICAL = 0,
SIDEBARLAYOUT_NORMAL = 1,
SIDEBARLAYOUT_COMPLEX = 2,
SIDEBARLAYOUT_LARGE = 3,
/* flags */
SIDEBARORIENTATION_LEFT = 8,
SIDEBARORIENTATION_RIGHT = 16,
SIDEBARLAYOUT_DYNHEIGHT = 32,
SIDEBARLAYOUT_VERTICALORIENTATION = 64,
SIDEBARLAYOUT_NOCLOSEBUTTONS = 128
};
enum {
SIDEBAR_GAP = 2 // gap between sidebar container window and content tab sheet border
};
CSideBar(TContainerData *pContainer);
~CSideBar();
void Init(const bool fForce = false);
void addSession(const TWindowData *dat, int position);
HRESULT removeSession(const TWindowData *dat);
void updateSession(const TWindowData *dat);
void processScrollerButtons(UINT cmd);
void Layout(const RECT *rc = 0, bool fOnlyCalc = false);
void setVisible(bool fNewVisibility);
void showAll(int showCmd);
const LONG getWidth() const { return(m_isVisible ? m_width + SIDEBAR_GAP : 0); }
const DWORD getFlags() const { return(m_dwFlags); }
const TContainerData* getContainer() const { return(m_pContainer); }
const bool isActive() const { return(m_isActive); }
const bool isVisible() const { return(m_isVisible); }
const CSideBarButton* getActiveItem() const { return(m_activeItem); }
const CSideBarButton* getScrollUp() const { return(m_up); }
const CSideBarButton* getScrollDown() const { return(m_down); }
bool isSkinnedContainer() const { return(CSkin::m_skinEnabled ? true : false); }
const UINT getLayoutId() const { return(m_uLayout); }
void invalidateButton(const TWindowData *dat);
const CSideBarButton* setActiveItem(const CSideBarButton *newItem)
{
CSideBarButton *oldItem = m_activeItem;
m_activeItem = const_cast<CSideBarButton *>(newItem);
if (oldItem)
::InvalidateRect(oldItem->getHwnd(), NULL, FALSE);
::InvalidateRect(m_activeItem->getHwnd(), NULL, FALSE);
scrollIntoView(m_activeItem);
return(oldItem);
}
/**
* this item has its close button currently hovered
* @param item: the CSideBarButton* which is hovered
*/
void setHoveredClose (CSideBarButton* item)
{
m_hoveredClose = item;
}
HWND getScrollWnd() const { return(m_hwndScrollWnd); }
const CSideBarButton* getHoveredClose() const { return(m_hoveredClose); }
const CSideBarButton* setActiveItem (const TWindowData *dat);
static LRESULT CALLBACK wndProcStub(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static const TSideBarLayout* getLayouts (int& uLayoutCount)
{
uLayoutCount = NR_LAYOUTS;
return(m_layouts);
}
void scrollIntoView (const CSideBarButton *item = 0);
void resizeScrollWnd (LONG x, LONG y, LONG width, LONG height) const;
private:
void createScroller();
void destroyScroller();
void populateAll();
void removeAll();
void Invalidate();
CSideBarButton* findSession(const TWindowData *dat);
CSideBarButton* findSession(const HANDLE hContact);
LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
HWND m_hwndScrollWnd;
OBJLIST<CSideBarButton> m_buttonlist; // our list of buttons
TContainerData* m_pContainer; // our master and commander...
LONG m_width; // required width of the bar (m_elementWidth + padding)
DWORD m_dwFlags;
CSideBarButton* m_up, *m_down; // the scroller buttons (up down)
CSideBarButton* m_activeItem; // active button item (for highlighting)
const CSideBarButton* m_hoveredClose; // item which must display an active close button
LONG m_topHeight, m_bottomHeight;
LONG m_firstVisibleOffset, m_totalItemHeight;
int m_iTopButtons, m_iBottomButtons;
LONG m_elementHeight, m_elementWidth; // width / height for a single element.
// can be dynamic (see measeureItem() in CSideBarButtonItem
bool m_isActive; // the sidebar is active (false, if it does _nothing at all_
bool m_isVisible; // visible aswell (not collapsed)
TSideBarLayout* m_currentLayout; // the layout in use. will be passed to new button items
UINT m_uLayout; // layout id number, currently in use
private:
/*
* layouts. m_layouts[] is static and contains layout descriptions
* renderer functions are static aswell
*/
static TSideBarLayout m_layouts[NR_LAYOUTS];
static void __fastcall m_DefaultBackgroundRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
static void __fastcall m_DefaultContentRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
static void __fastcall m_AdvancedContentRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
static const SIZE& __fastcall m_measureAdvancedVertical(CSideBarButton *item);
};
inline void CSideBarButton::setLayout(const TSideBarLayout *newLayout)
{
m_sideBarLayout = newLayout;
}
#endif
|