/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <windows.h>
#include <commctrl.h>
#include "../../../../core/src/util/ZLKeyUtil.h"
#include "W32Control.h"
#include "W32ControlCollection.h"
#include "../../../../core/src/win32/util/W32WCHARUtil.h"
static const WORD CLASS_BUTTON = 0x0080;
static const WORD CLASS_EDIT = 0x0081;
static const WORD CLASS_STATIC = 0x0082;
static const WORD CLASS_LISTBOX = 0x0083;
static const WORD CLASS_SCROLLBAR = 0x0084;
static const WORD CLASS_COMBOBOX = 0x0085;
static const WCHAR CLASSNAME_SPINNER[] = UPDOWN_CLASSW;
W32Control::W32Control(DWORD style) : myStyle(style | WS_CHILD), myX(1), myY(1), mySize(Size(1, 1)), myEnabled(true), myOwner(0), myWindow(0) {
}
void W32Control::setEnabled(bool enabled) {
if (myEnabled != enabled) {
myEnabled = enabled;
if (myWindow != 0) {
EnableWindow(myWindow, myEnabled);
}
}
}
bool W32Control::isEnabled() const {
return myEnabled;
}
void W32Control::setVisible(bool visible) {
if (visible != isVisible()) {
if (visible) {
myStyle |= WS_VISIBLE;
} else {
myStyle &= ~WS_VISIBLE;
}
if (myWindow != 0) {
ShowWindow(myWindow, visible ? SW_SHOW : SW_HIDE);
}
if (myOwner != 0) {
myOwner->invalidate();
}
}
}
bool W32Control::isVisible() const {
return (myStyle & WS_VISIBLE) == WS_VISIBLE;
}
void W32Control::init(HWND parent, W32ControlCollection *collection) {
myOwner = collection;
myWindow = GetDlgItem(parent, collection->addControl(this));
if (!myEnabled) {
EnableWindow(myWindow, false);
}
}
W32StandardControl::W32StandardControl(DWORD style) : W32Control(style) {
}
int W32StandardControl::controlNumber() const {
return 1;
}
int W32StandardControl::allocationSize() const {
return 14;
}
void W32StandardControl::allocate(WORD *&p, short &id) const {
*p++ = LOWORD(myStyle);
*p++ = HIWORD(myStyle);
*p++ = 0;
*p++ = 0;
*p++ = myX;
*p++ = myY;
/*
if ((mySize.Width == 0) || (mySize.Height == 0)) {
mySize = minimumSize();
}
*/
*p++ = mySize.Width;
*p++ = mySize.Height;
*p++ = id++;
*p++ = 0xFFFF;
*p++ = classId();
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
void W32Control::setPosition(int x, int y, Size size) {
bool doMove = (myX != x) || (myY != y);
bool doResize = mySize != size;
myX = x;
myY = y;
mySize = size;
if ((doResize || doMove) && (myWindow != 0)) {
RECT r;
r.left = x;
r.top = y;
r.right = x + size.Width;
r.bottom = y + size.Height;
MapDialogRect(GetParent(myWindow), &r);
DWORD flags = SWP_NOZORDER | SWP_NOOWNERZORDER;
if (!doResize) {
flags |= SWP_NOSIZE;
}
if (!doMove) {
flags |= SWP_NOMOVE;
}
SetWindowPos(myWindow, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, flags);
}
}
void W32Control::commandCallback(DWORD) {
}
void W32Control::notificationCallback(LPARAM) {
}
void W32Control::drawItemCallback(DRAWITEMSTRUCT&) {
}
const std::string W32PushButton::RELEASED_EVENT = "PushButton: released";
W32PushButton::W32PushButton(const std::string &text, ButtonType type) : W32StandardControl(BS_PUSHBUTTON | WS_TABSTOP), myText(text), myType(type) {
//DWORD style = (it == myButtons.begin()) ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON;
}
W32Widget::Size W32PushButton::minimumSize() const {
return Size(4 * (ZLUnicodeUtil::utf8Length(myText) + 3), 15);
}
void W32PushButton::allocate(WORD *&p, short &id) const {
if (myType == NORMAL_BUTTON) {
W32StandardControl::allocate(p, id);
} else {
short specialId = (myType == OK_BUTTON) ? IDOK : IDCANCEL;
W32StandardControl::allocate(p, specialId);
}
}
WORD W32PushButton::classId() const {
return CLASS_BUTTON;
}
void W32PushButton::init(HWND parent, W32ControlCollection *collection) {
myOwner = collection;
short id = -1;
if (myType == OK_BUTTON) {
id = IDOK;
} else if (myType == CANCEL_BUTTON) {
id = IDCANCEL;
}
myWindow = GetDlgItem(parent, collection->addControl(this, id));
if (!myEnabled) {
EnableWindow(myWindow, false);
}
::setWindowText(myWindow, myText);
}
void W32PushButton::commandCallback(DWORD) {
fireEvent(RELEASED_EVENT);
}
W32Label::W32Label(const std::string &text, Alignment alignment) : W32StandardControl(alignment), myText(text) {
myStringCounter = 1;
myMaxLength = 0;
int index = 0;
int newIndex;
while ((newIndex = myText.find('\n', index)) != -1) {
++myStringCounter;
myMaxLength = std::max(
myMaxLength,
(unsigned short)ZLUnicodeUtil::utf8Length(myText.data() + index, newIndex - index)
);
index = newIndex + 1;
}
myMaxLength = std::max(
myMaxLength,
(unsigned short)ZLUnicodeUtil::utf8Length(myText.data() + index, myText.length() - index)
);
}
W32Widget::Size W32Label::minimumSize() const {
return Size(4 * myMaxLength, 12 * myStringCounter);
}
void W32Label::setPosition(int x, int y, Size size) {
::setWindowText(myWindow, "");
W32StandardControl::setPosition(x, y + 2, Size(size.Width, size.Height - 2));
::setWindowText(myWindow, myText);
}
WORD W32Label::classId() const {
return CLASS_STATIC;
}
void W32Label::init(HWND parent, W32ControlCollection *collection) {
W32StandardControl::init(parent, collection);
::setWindowText(myWindow, myText);
}
W32StandardIcon::W32StandardIcon(IconId iconId) : W32StandardControl(SS_CENTER | SS_ICON), myIconId(iconId) {
}
W32Widget::Size W32StandardIcon::minimumSize() const {
// TODO: why multiplier 2?
return Size(SM_CXICON * 2, SM_CYICON * 2);
}
WORD W32StandardIcon::classId() const {
return CLASS_STATIC;
}
void W32StandardIcon::init(HWND parent, W32ControlCollection *collection) {
W32StandardControl::init(parent, collection);
WCHAR *icon;
switch (myIconId) {
case ID_INFORMATION:
icon = IDI_INFORMATION;
break;
case ID_QUESTION:
icon = IDI_QUESTION;
break;
case ID_ERROR:
icon = IDI_ERROR;
break;
default:
icon = IDI_APPLICATION;
break;
}
SendMessage(myWindow, STM_SETICON, (WPARAM)LoadIcon(0, icon), 0);
}
const std::string W32CheckBox::STATE_CHANGED_EVENT = "CheckBox: state changed";
W32CheckBox::W32CheckBox(const std::string &text) : W32StandardControl(BS_AUTOCHECKBOX | WS_TABSTOP), myText(text), myChecked(false) {
}
W32Widget::Size W32CheckBox::minimumSize() const {
return Size(4 * (ZLUnicodeUtil::utf8Length(myText) + 1), 12);
}
WORD W32CheckBox::classId() const {
return CLASS_BUTTON;
}
void W32CheckBox::init(HWND parent, W32ControlCollection *collection) {
W32StandardControl::init(parent, collection);
::setWindowText(myWindow, myText);
SendMessage(myWindow, BM_SETCHECK, myChecked ? BST_CHECKED : BST_UNCHECKED, 0);
}
void W32CheckBox::setEditable(bool editable) {
if (editable) {
myStyle &= ~WS_DISABLED;
} else {
myStyle |= WS_DISABLED;
}
if (myWindow != 0) {
// TODO: check
SetWindowLong(myWindow, GWL_STYLE, myStyle);
}
}
void W32CheckBox::setChecked(bool checked) {
if (checked != myChecked) {
myChecked = checked;
if (myWindow != 0) {
SendMessage(myWindow, BM_SETCHECK, myChecked ? BST_CHECKED : BST_UNCHECKED, 0);
}
fireEvent(STATE_CHANGED_EVENT);
}
}
bool W32CheckBox::isChecked() const {
return myChecked;
}
void W32CheckBox::commandCallback(DWORD) {
if (myChecked != (SendMessage(myWindow, BM_GETCHECK, 0, 0) == BST_CHECKED)) {
myChecked = !myChecked;
fireEvent(STATE_CHANGED_EVENT);
}
}
const std::string