mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-23 13:31:49 +00:00
Improved input method support by M. Iwami. I fixed some typo, and simplified the code a bit.
* Painter: - preeditText(), dashedUnderline(): new methods for CJK support. * GuiWorkArea: - inputMethodQuery(): new Qt inherited method for proper CJK support. - inputMethodEvent(): now properly take care of input methods. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@17671 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
44c4c02c5d
commit
099a4adc92
@ -84,6 +84,39 @@ void Painter::buttonText(int x, int y, docstring const & str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Painter::preeditText(int x, int y, char_type c,
|
||||||
|
LyXFont const & font, preedit_style style)
|
||||||
|
{
|
||||||
|
LyXFont temp_font = font;
|
||||||
|
FontMetrics const & fm = theFontMetrics(font);
|
||||||
|
int ascent = fm.maxAscent();
|
||||||
|
int descent = fm.maxDescent();
|
||||||
|
int height = ascent + descent;
|
||||||
|
int width = fm.width(c);
|
||||||
|
|
||||||
|
switch (style) {
|
||||||
|
case preedit_default:
|
||||||
|
// default unselecting mode.
|
||||||
|
fillRectangle(x, y - height + 1, width, height, LColor::background);
|
||||||
|
dashedUnderline(font, x, y - descent + 1, width);
|
||||||
|
break;
|
||||||
|
case preedit_selecting:
|
||||||
|
// We are in selecting mode: white text on black background.
|
||||||
|
fillRectangle(x, y - height + 1, width, height, LColor::black);
|
||||||
|
temp_font.setColor(LColor::white);
|
||||||
|
break;
|
||||||
|
case preedit_cursor:
|
||||||
|
// The character comes with a cursor.
|
||||||
|
fillRectangle(x, y - height + 1, width, height, LColor::background);
|
||||||
|
underline(font, x, y - descent + 1, width);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text(x, y - descent + 1, c, temp_font);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Painter::underline(LyXFont const & f, int x, int y, int width)
|
void Painter::underline(LyXFont const & f, int x, int y, int width)
|
||||||
{
|
{
|
||||||
FontMetrics const & fm = theFontMetrics(f);
|
FontMetrics const & fm = theFontMetrics(f);
|
||||||
@ -97,5 +130,20 @@ void Painter::underline(LyXFont const & f, int x, int y, int width)
|
|||||||
fillRectangle(x, y + below, width, below + height, f.color());
|
fillRectangle(x, y + below, width, below + height, f.color());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Painter::dashedUnderline(LyXFont const & f, int x, int y, int width)
|
||||||
|
{
|
||||||
|
FontMetrics const & fm = theFontMetrics(f);
|
||||||
|
|
||||||
|
int const below = max(fm.maxDescent() / 2, 2);
|
||||||
|
int height = max((fm.maxDescent() / 4) - 1, 1);
|
||||||
|
|
||||||
|
if (height >= 2)
|
||||||
|
height += below;
|
||||||
|
|
||||||
|
for (int n = 0; n < height; ++n)
|
||||||
|
line(x, y + below + n, x + width, y + below + n, f.color(), line_onoffdash);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace lyx
|
} // namespace lyx
|
||||||
|
@ -66,6 +66,14 @@ public:
|
|||||||
line_onoffdash //< dashes with spaces
|
line_onoffdash //< dashes with spaces
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// possible character styles of preedit string.
|
||||||
|
/// This is used for CJK input method support.
|
||||||
|
enum preedit_style {
|
||||||
|
preedit_default, //< when unselecting, no cursor and dashed underline.
|
||||||
|
preedit_selecting, //< when selecting.
|
||||||
|
preedit_cursor //< with cursor.
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~Painter() {}
|
virtual ~Painter() {}
|
||||||
|
|
||||||
/// draw a line from point to point
|
/// draw a line from point to point
|
||||||
@ -157,11 +165,19 @@ public:
|
|||||||
void buttonText(int x, int baseline, docstring const & s,
|
void buttonText(int x, int baseline, docstring const & s,
|
||||||
LyXFont const & font, bool mouseHover);
|
LyXFont const & font, bool mouseHover);
|
||||||
|
|
||||||
|
/// draw a character of a preedit string for cjk support.
|
||||||
|
int preeditText(int x, int y,
|
||||||
|
char_type c, LyXFont const & f, preedit_style style);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// check the font, and if set, draw an underline
|
/// check the font, and if set, draw an underline
|
||||||
void underline(LyXFont const & f,
|
void underline(LyXFont const & f,
|
||||||
int x, int y, int width);
|
int x, int y, int width);
|
||||||
|
|
||||||
|
/// check the font, and if set, draw an dashed underline
|
||||||
|
void dashedUnderline(LyXFont const & f,
|
||||||
|
int x, int y, int width);
|
||||||
|
|
||||||
/// draw a bevelled button border
|
/// draw a bevelled button border
|
||||||
void buttonFrame(int x, int y, int w, int h);
|
void buttonFrame(int x, int y, int w, int h);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "LColor.h"
|
#include "LColor.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "lyxrc.h"
|
#include "lyxrc.h"
|
||||||
|
#include "lyxtext.h"
|
||||||
|
|
||||||
#include "support/filetools.h" // LibFileSearch
|
#include "support/filetools.h" // LibFileSearch
|
||||||
#include "support/os.h"
|
#include "support/os.h"
|
||||||
@ -44,6 +45,7 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QInputContext>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/current_function.hpp>
|
#include <boost/current_function.hpp>
|
||||||
@ -160,7 +162,8 @@ SyntheticMouseEvent::SyntheticMouseEvent()
|
|||||||
|
|
||||||
|
|
||||||
GuiWorkArea::GuiWorkArea(int w, int h, int id, LyXView & lyx_view)
|
GuiWorkArea::GuiWorkArea(int w, int h, int id, LyXView & lyx_view)
|
||||||
: WorkArea(id, lyx_view), need_resize_(false), schedule_redraw_(false)
|
: WorkArea(id, lyx_view), need_resize_(false), schedule_redraw_(false),
|
||||||
|
preedit_lines_(1)
|
||||||
{
|
{
|
||||||
screen_ = QPixmap(viewport()->width(), viewport()->height());
|
screen_ = QPixmap(viewport()->width(), viewport()->height());
|
||||||
cursor_ = new frontend::CursorWidget();
|
cursor_ = new frontend::CursorWidget();
|
||||||
@ -299,6 +302,8 @@ void GuiWorkArea::mousePressEvent(QMouseEvent * e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputContext()->reset();
|
||||||
|
|
||||||
FuncRequest const cmd(LFUN_MOUSE_PRESS, e->x(), e->y(),
|
FuncRequest const cmd(LFUN_MOUSE_PRESS, e->x(), e->y(),
|
||||||
q_button_state(e->button()));
|
q_button_state(e->button()));
|
||||||
dispatch(cmd, q_key_state(e->modifiers()));
|
dispatch(cmd, q_key_state(e->modifiers()));
|
||||||
@ -573,8 +578,16 @@ void GuiWorkArea::removeCursor()
|
|||||||
|
|
||||||
void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
|
void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
|
||||||
{
|
{
|
||||||
QString const & text = e->commitString();
|
QString const & commit_string = e->commitString();
|
||||||
if (!text.isEmpty()) {
|
docstring const & preedit_string
|
||||||
|
= qstring_to_ucs4(e->preeditString());
|
||||||
|
|
||||||
|
if(greyed_out_) {
|
||||||
|
e->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!commit_string.isEmpty()) {
|
||||||
|
|
||||||
lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
|
lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
|
||||||
<< " preeditString =" << fromqstr(e->preeditString())
|
<< " preeditString =" << fromqstr(e->preeditString())
|
||||||
@ -583,26 +596,145 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
|
|||||||
|
|
||||||
int key = 0;
|
int key = 0;
|
||||||
|
|
||||||
// FIXME Abdel 10/02/07: Remove?
|
// FIXME Iwami 04/01/07: we should take care also of UTF16 surrogates here.
|
||||||
// needed to make math superscript work on some systems
|
for (int i = 0; i < commit_string.size(); ++i) {
|
||||||
// ideally, such special coding should not be necessary
|
QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, commit_string[i]);
|
||||||
if (text == "^")
|
|
||||||
key = Qt::Key_AsciiCircum;
|
|
||||||
|
|
||||||
// FIXME Abdel 10/02/07: Minimal support for CJK, aka systems
|
|
||||||
// with input methods. What should we do with e->preeditString()?
|
|
||||||
// Do we need an inputMethodQuery() method?
|
|
||||||
// FIXME 2: we should take care also of UTF16 surrogates here.
|
|
||||||
for (int i = 0; i < text.size(); ++i) {
|
|
||||||
// FIXME: Needs for investigation, this key is not really used,
|
|
||||||
// the ctor below just check if key is different from 0.
|
|
||||||
QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, text[i]);
|
|
||||||
keyPressEvent(&ev);
|
keyPressEvent(&ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide the cursor during the kana-kanji transformation.
|
||||||
|
if (preedit_string.empty())
|
||||||
|
startBlinkingCursor();
|
||||||
|
else
|
||||||
|
stopBlinkingCursor();
|
||||||
|
|
||||||
|
// if last_width is last length of preedit string.
|
||||||
|
static int last_width = 0;
|
||||||
|
if (!last_width && preedit_string.empty()) {
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLPainter pain(&screen_);
|
||||||
|
buffer_view_->updateMetrics(false);
|
||||||
|
paintText(*buffer_view_, pain);
|
||||||
|
LyXFont font = buffer_view_->cursor().getFont();
|
||||||
|
FontMetrics const & fm = theFontMetrics(font);
|
||||||
|
int height = fm.maxHeight();
|
||||||
|
int cur_x = cursor_->rect().left();
|
||||||
|
int cur_y = cursor_->rect().bottom();
|
||||||
|
|
||||||
|
// redraw area of preedit string.
|
||||||
|
update(0, cur_y - height, GuiWorkArea::width(),
|
||||||
|
(height + 1) * preedit_lines_);
|
||||||
|
|
||||||
|
if (preedit_string.empty()) {
|
||||||
|
last_width = 0;
|
||||||
|
preedit_lines_ = 1;
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Describe these variables.
|
||||||
|
last_width = 1;
|
||||||
|
size_t cur_pos = 0;
|
||||||
|
size_t rStart = 0;
|
||||||
|
size_t rLength = 0;
|
||||||
|
int cur_visible = 0;
|
||||||
|
QList<QInputMethodEvent::Attribute> const & att(e->attributes());
|
||||||
|
|
||||||
|
// get attributes of input method cursor.
|
||||||
|
for (int i = 0; i < att.size(); ++i) {
|
||||||
|
if (att.at(i).type == QInputMethodEvent::Cursor) {
|
||||||
|
cur_pos = att.at(i).start;
|
||||||
|
cur_visible = att.at(i).length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t preedit_length = preedit_string.length();
|
||||||
|
|
||||||
|
// get position of selection in input method.
|
||||||
|
// FIXME: isn't there a way to do this simplier?
|
||||||
|
if (cur_pos < preedit_length) {
|
||||||
|
for (int i = 0; i < att.size(); ++i) {
|
||||||
|
if (att.at(i).type == QInputMethodEvent::TextFormat) {
|
||||||
|
if (att.at(i).start <= int(cur_pos)
|
||||||
|
&& int(cur_pos) < att.at(i).start + att.at(i).length) {
|
||||||
|
rStart = att.at(i).start;
|
||||||
|
rLength = att.at(i).length;
|
||||||
|
if (cur_visible == 0)
|
||||||
|
cur_pos += rLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rStart = cur_pos;
|
||||||
|
rLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int const right_margin = lyx::rightMargin();
|
||||||
|
Painter::preedit_style ps;
|
||||||
|
// Most often there would be only one line:
|
||||||
|
preedit_lines_ = 1;
|
||||||
|
for (size_t pos = 0; pos != preedit_length; ++pos) {
|
||||||
|
char_type const typed_char = preedit_string[pos];
|
||||||
|
// reset preedit string style
|
||||||
|
ps = Painter::preedit_default;
|
||||||
|
|
||||||
|
// if we reached the right extremity of the screen, go to next line.
|
||||||
|
if (cur_x + fm.width(typed_char) > GuiWorkArea::width() - right_margin) {
|
||||||
|
cur_x = right_margin;
|
||||||
|
cur_y += height + 1;
|
||||||
|
++preedit_lines_;
|
||||||
|
}
|
||||||
|
// preedit strings are displayed with dashed underline
|
||||||
|
// and partial strings are displayed white on black indicating
|
||||||
|
// that we are in selecting mode in the input method.
|
||||||
|
// FIXME: rLength == preedit_length is not a changing condition
|
||||||
|
// FIXME: should be put out of the loop.
|
||||||
|
if (pos >= rStart
|
||||||
|
&& pos < rStart + rLength
|
||||||
|
&& !(cur_pos < rLength && rLength == preedit_length))
|
||||||
|
ps = Painter::preedit_selecting;
|
||||||
|
|
||||||
|
if (pos == cur_pos
|
||||||
|
&& (cur_pos < rLength && rLength == preedit_length))
|
||||||
|
ps = Painter::preedit_cursor;
|
||||||
|
|
||||||
|
// draw one character and update cur_x.
|
||||||
|
cur_x += pain.preeditText(cur_x, cur_y, typed_char, font, ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the preedit string screen area.
|
||||||
|
update(0, cur_y - preedit_lines_*height, GuiWorkArea::width(),
|
||||||
|
(height + 1) * preedit_lines_);
|
||||||
|
|
||||||
|
// Don't forget to accept the event!
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant GuiWorkArea::inputMethodQuery(Qt::InputMethodQuery query) const
|
||||||
|
{
|
||||||
|
QRect cur_r(0,0,0,0);
|
||||||
|
switch (query) {
|
||||||
|
// this is the CJK-specific composition window position.
|
||||||
|
case Qt::ImMicroFocus:
|
||||||
|
cur_r = cursor_->rect();
|
||||||
|
if (preedit_lines_ != 1)
|
||||||
|
cur_r.moveLeft(10);
|
||||||
|
cur_r.moveBottom(cur_r.bottom() + cur_r.height() * preedit_lines_);
|
||||||
|
// return lower right of cursor in LyX.
|
||||||
|
return cur_r;
|
||||||
|
default:
|
||||||
|
return QWidget::inputMethodQuery(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace lyx
|
} // namespace lyx
|
||||||
|
|
||||||
|
@ -142,6 +142,8 @@ private:
|
|||||||
void keyPressEvent(QKeyEvent * ev);
|
void keyPressEvent(QKeyEvent * ev);
|
||||||
/// IM events
|
/// IM events
|
||||||
void inputMethodEvent(QInputMethodEvent * ev);
|
void inputMethodEvent(QInputMethodEvent * ev);
|
||||||
|
/// IM query
|
||||||
|
QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/// Adjust the LyX buffer view with the position of the scrollbar.
|
/// Adjust the LyX buffer view with the position of the scrollbar.
|
||||||
@ -173,6 +175,8 @@ private:
|
|||||||
bool need_resize_;
|
bool need_resize_;
|
||||||
///
|
///
|
||||||
bool schedule_redraw_;
|
bool schedule_redraw_;
|
||||||
|
///
|
||||||
|
int preedit_lines_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
|
Loading…
Reference in New Issue
Block a user