Skip to content

Commit

Permalink
Show aux info messages by using Ime::MessageWindow class.
Browse files Browse the repository at this point in the history
  • Loading branch information
PCMan committed Sep 19, 2013
1 parent b7bcac0 commit 73ddae8
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 71 deletions.
65 changes: 63 additions & 2 deletions ChewingTextService/ChewingTextService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ TextService::TextService(ImeModule* module):
langMode_(-1),
shapeMode_(-1),
lastKeyDownCode_(0),
messageWindow_(NULL),
messageTimerId_(0),
candidateWindow_(NULL),
chewingContext_(NULL) {

Expand Down Expand Up @@ -101,6 +103,9 @@ TextService::~TextService(void) {
if(candidateWindow_)
delete candidateWindow_;

if(messageWindow_)
hideMessage();

if(switchLangButton_)
switchLangButton_->Release();
if(switchShapeButton_)
Expand All @@ -111,7 +116,6 @@ TextService::~TextService(void) {

// virtual
void TextService::onActivate() {

DWORD configStamp = globalCompartmentValue(g_configChangedGuid);
config().reloadIfNeeded(configStamp);

Expand All @@ -124,6 +128,8 @@ void TextService::onDeactivate() {
lastKeyDownCode_ = 0;
freeChewingContext();

hideMessage();

if(candidateWindow_) {
delete candidateWindow_;
candidateWindow_ = NULL;
Expand Down Expand Up @@ -267,6 +273,8 @@ bool TextService::onKeyDown(Ime::KeyEvent& keyEvent, Ime::EditSession* session)
case VK_NEXT:
::chewing_handle_PageDown(chewingContext_);
break;
default: // we don't know this key. ignore it!
return false;
}
}

Expand Down Expand Up @@ -357,7 +365,10 @@ bool TextService::onKeyDown(Ime::KeyEvent& keyEvent, Ime::EditSession* session)
char* str = ::chewing_aux_String(chewingContext_);
wchar_t* wstr = utf8ToUtf16(str, NULL);
::chewing_free(str);
// TODO: show the message to the user
// show the message to the user
// FIXME: sometimes libchewing shows the same aux info
// for subsequent key events... I think this is a bug.
showMessage(session, wstr);
delete []wstr;
}
return true;
Expand Down Expand Up @@ -643,6 +654,56 @@ void TextService::hideCandidates() {
showingCandidates_ = false;
}


// message window
void TextService::showMessage(Ime::EditSession* session, std::wstring message, int duration) {
// remove previous message if there's any
hideMessage();
// FIXME: reuse the window whenever possible
messageWindow_ = new Ime::MessageWindow(this, session);
messageWindow_->setText(message);

int x = 0, y = 0;
if(isComposing()) {
RECT rc;
if(selectionRect(session, &rc)) {
x = rc.left;
y = rc.bottom;
}
}
messageWindow_->move(x, y);
messageWindow_->show();

messageTimerId_ = ::SetTimer(messageWindow_->hwnd(), 1, duration * 1000, (TIMERPROC)TextService::onMessageTimeout);
}

void TextService::hideMessage() {
if(messageTimerId_) {
::KillTimer(messageWindow_->hwnd(), messageTimerId_);
messageTimerId_ = 0;
}
if(messageWindow_) {
delete messageWindow_;
messageWindow_ = NULL;
}
}

// called when the message window timeout
void TextService::onMessageTimeout() {
hideMessage();
}

// static
void CALLBACK TextService::onMessageTimeout(HWND hwnd, UINT msg, UINT_PTR id, DWORD time) {
Ime::MessageWindow* messageWindow = (Ime::MessageWindow*)Ime::Window::fromHwnd(hwnd);
assert(messageWindow);
if(messageWindow) {
TextService* pThis = (Chewing::TextService*)messageWindow->textService();
pThis->onMessageTimeout();
}
}


void TextService::updateLangButtons() {
if(!chewingContext_)
return;
Expand Down
10 changes: 10 additions & 0 deletions ChewingTextService/ChewingTextService.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <LibIME/TextService.h>
#include <LibIME/CandidateWindow.h>
#include <LibIME/MessageWindow.h>
#include <LibIME/EditSession.h>
#include <LibIME/LangBarButton.h>
#include <chewing.h>
Expand Down Expand Up @@ -80,6 +81,12 @@ class TextService: public Ime::TextService {
void updateCandidates(Ime::EditSession* session);
void hideCandidates();

// message window
void showMessage(Ime::EditSession* session, std::wstring message, int duration = 3);
void hideMessage();
void onMessageTimeout();
static void CALLBACK onMessageTimeout(HWND hwnd, UINT msg, UINT_PTR id, DWORD time);

void updateLangButtons(); // update status of language bar buttons

// reload configurations if changes are detected
Expand All @@ -96,6 +103,9 @@ class TextService: public Ime::TextService {
Ime::CandidateWindow* candidateWindow_;
bool showingCandidates_;

Ime::MessageWindow* messageWindow_;
UINT messageTimerId_;

Ime::LangBarButton* switchLangButton_;
Ime::LangBarButton* switchShapeButton_;

Expand Down
6 changes: 0 additions & 6 deletions ChewingTextService/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@
#define IDC_BUTTON41 1069
#define IDC_BUTTON42 1073
#define IDC_BUTTON43 1074
#define IDI_APPLICATION 32512
#define IDI_HAND 32513
#define IDI_QUESTION 32514
#define IDI_EXCLAMATION 32515
#define IDI_ASTERISK 32516
#define IDI_WINLOGO 32517
#define ID_SETTINGS_ 40003
#define ID_ABOUT 40005
#define ID_CHECK_NEW_VER 40006
Expand Down
86 changes: 34 additions & 52 deletions libIME/Tooltip.cpp → libIME/MessageWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,44 @@
// Boston, MA 02110-1301, USA.
//

#include "Tooltip.h"
#include "MessageWindow.h"
#include "TextService.h"
#include "DrawUtils.h"

namespace Ime {

Tooltip::Tooltip(void):
autoDestroy_(true),
timerId_(0) {
MessageWindow::MessageWindow(TextService* service, EditSession* session):
textService_(service) {
HWND parent;
if(session && service->isImmersive())
parent = service->compositionWindow(session);
else
parent = HWND_DESKTOP;
create(parent, WS_POPUP|WS_CLIPCHILDREN, WS_EX_TOOLWINDOW);
}

Tooltip::~Tooltip(void) {
if(timerId_)
KillTimer(hwnd_, timerId_);
MessageWindow::~MessageWindow(void) {
}

LRESULT Tooltip::wndProc(UINT msg, WPARAM wp, LPARAM lp) {
void MessageWindow::setText(std::wstring text) {
// FIXMEl: use different appearance under immersive mode
int margin = 4;
text_ = text;
SIZE size = {0};
HDC dc = GetDC(hwnd_);
HGDIOBJ old_font = SelectObject(dc, GetStockObject(DEFAULT_GUI_FONT));
GetTextExtentPointW(dc, text_.c_str(), text_.length(), &size);
SelectObject(dc, old_font);
ReleaseDC(hwnd_, dc);

SetWindowPos(hwnd_, HWND_TOPMOST, 0, 0,
size.cx + margin * 2, size.cy + margin * 2, SWP_NOACTIVATE|SWP_NOMOVE);
if(IsWindowVisible(hwnd_))
InvalidateRect(hwnd_, NULL, TRUE);
}


LRESULT MessageWindow::wndProc(UINT msg, WPARAM wp, LPARAM lp) {
switch(msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
Expand All @@ -41,17 +63,6 @@ LRESULT Tooltip::wndProc(UINT msg, WPARAM wp, LPARAM lp) {
EndPaint(hwnd_, &ps);
}
break;
case WM_TIMER:
hideTip();
if(autoDestroy_) {
::DestroyWindow(hwnd_);
}
break;
case WM_NCDESTROY:
if(autoDestroy_) {
delete this;
return 0;
}
case WM_MOUSEACTIVATE:
return MA_NOACTIVATE;
default:
Expand All @@ -60,8 +71,8 @@ LRESULT Tooltip::wndProc(UINT msg, WPARAM wp, LPARAM lp) {
return 0;
}

void Tooltip::onPaint(PAINTSTRUCT& ps) {
int len = text.length();
void MessageWindow::onPaint(PAINTSTRUCT& ps) {
int len = text_.length();
RECT rc, textrc = {0};
GetClientRect(hwnd_, &rc);
::FillSolidRect(ps.hdc, &rc, ::GetSysColor(COLOR_INFOBK));
Expand All @@ -72,41 +83,12 @@ void Tooltip::onPaint(PAINTSTRUCT& ps) {
HGDIOBJ old_font = SelectObject(ps.hdc, GetStockObject(DEFAULT_GUI_FONT));

SIZE size;
GetTextExtentPoint32W(ps.hdc, text.c_str(), len, &size);
GetTextExtentPoint32W(ps.hdc, text_.c_str(), len, &size);
rc.top += (rc.bottom - size.cy)/2;
rc.left += (rc.right - size.cx)/2;
ExtTextOutW(ps.hdc, rc.left, rc.top, 0, &textrc, text.c_str(), len, NULL);
ExtTextOutW(ps.hdc, rc.left, rc.top, 0, &textrc, text_.c_str(), len, NULL);

SelectObject(ps.hdc, old_font);
}

void Tooltip::showTip(int x, int y, std::wstring tip_text, int duration) {
text = tip_text;
SIZE size = {0};
HDC dc = GetDC(hwnd_);
HGDIOBJ old_font = SelectObject(dc, GetStockObject(DEFAULT_GUI_FONT));
GetTextExtentPointW(dc, text.c_str(), text.length(), &size);
SelectObject(dc, old_font);
ReleaseDC(hwnd_, dc);

SetWindowPos(hwnd_, HWND_TOPMOST, x, y, size.cx + 4, size.cy + 4, SWP_NOACTIVATE);
if(IsWindowVisible(hwnd_))
InvalidateRect(hwnd_, NULL, TRUE);
else
ShowWindow(hwnd_, SW_SHOWNA);
if(duration > 0) {
if(timerId_)
KillTimer(hwnd_, timerId_);
timerId_ = SetTimer(hwnd_, 1, duration, NULL);
}
}

void Tooltip::hideTip(void) {
if(timerId_) {
KillTimer(hwnd_, timerId_);
timerId_ = 0;
}
hide();
}

} // namespace Ime
28 changes: 17 additions & 11 deletions libIME/Tooltip.h → libIME/MessageWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,35 @@
#ifndef IME_TOOLTIP_H
#define IME_TOOLTIP_H

#include "imewindow.h"
#include "ImeWindow.h"
#include "EditSession.h"
#include <string>

namespace Ime {

class Tooltip : public ImeWindow {
class TextService;

class MessageWindow : public ImeWindow {
public:
Tooltip(void);
virtual ~Tooltip(void);
void showTip(int x, int y, std::wstring tip_text, int duration = 0);
void hideTip(void);
void setAutoDestroy(bool autoDestroy = true) {
autoDestroy_ = autoDestroy;
MessageWindow(TextService* service, EditSession* session = NULL);
virtual ~MessageWindow(void);

std::wstring text() {
return text_;
}
void setText(std::wstring text);

TextService* textService() {
return textService_;
}

protected:
LRESULT wndProc(UINT msg, WPARAM wp, LPARAM lp);
void onPaint(PAINTSTRUCT& ps);

private:
UINT timerId_;
std::wstring text;
bool autoDestroy_;
std::wstring text_;
TextService* textService_;
};

}
Expand Down
5 changes: 5 additions & 0 deletions libIME/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ class Window {

static bool registerClass(HINSTANCE hinstance);

static Window* fromHwnd(HWND hwnd) {
std::map<HWND, Window*>::iterator it = hwndMap_.find(hwnd);
return it != hwndMap_.end() ? it->second : NULL;
}

protected:
static LRESULT _wndProc(HWND hwnd , UINT msg, WPARAM wp , LPARAM lp);
virtual LRESULT wndProc(UINT msg, WPARAM wp , LPARAM lp);
Expand Down

0 comments on commit 73ddae8

Please sign in to comment.