Removing almost all animated over states in IconButton.

This commit is contained in:
John Preston 2016-11-01 15:46:34 +03:00
parent e08f5437a6
commit c932f3d9df
44 changed files with 435 additions and 307 deletions

View file

@ -594,7 +594,7 @@ msgImgReplyBarColor: #ffffff;
msgBotKbDuration: 200;
msgBotKbFont: semiboldFont;
msgBotKbOverBg: #fffffffc;
msgBotKbOverBg: #ffffff1a;
msgBotKbIconPadding: 2px;
msgBotKbUrlIcon: icon {{ "inline_button_url", #ffffff }};
msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", #ffffff }};
@ -900,7 +900,8 @@ contactsScroll: flatScroll(boxScroll) {
deltab: 0px;
}
simpleCloseIcon: icon {{ "simple_close", #000000 }};
simpleCloseIcon: icon {{ "simple_close", #c7c7c7 }};
simpleCloseIconOver: icon {{ "simple_close", #a3a3a3 }};
boxPhotoPadding: margins(28px, 28px, 28px, 18px);
boxPhotoCompressedPadding: margins(0px, 2px, 0px, 22px);
@ -1197,7 +1198,5 @@ settingsFixedBarCloseIcon: icon {{ "box_button_close", settingsFixedBarBg }};
notifyFadeRight: icon {{ "fade_horizontal_right", notificationBg }};
emojiPanBg: #ffffff;
emojiPanCategories: #f7f7f7;
stickerIconLeft: icon {{ "fade_horizontal_left", emojiPanCategories }};
stickerIconRight: icon {{ "fade_horizontal_right", emojiPanCategories }};

View file

@ -82,8 +82,7 @@ photoCropFadeBg: #0000007f;
photoCropPointFg: #ffffff7f;
// settings
settingsBg: windowBg;
settingsFixedBarBg: settingsBg;
settingsFixedBarBg: boxBg;
settingsCloseFg: cancelIconFg;
settingsCloseFgOver: cancelIconFgOver;
@ -101,7 +100,14 @@ introErrorFg: windowTextFg;
// history
topBarBg: windowBg;
emojiPanBg: windowBg;
emojiPanCategories: #f7f7f7 | windowBg;
emojiPanHeaderFg: #999999 | windowSubTextFg;
emojiPanHeaderBg: #fffffff2 | emojiPanBg;
historyComposeAreaBg: windowBg;
historyComposeIconFg: #cccccc;
historyComposeIconFgOver: #bebebe;
historyPinnedBg: historyComposeAreaBg;
historyReplyBg: historyComposeAreaBg;
historyReplyCancelIconFg: cancelIconFg;
@ -109,6 +115,7 @@ historyReplyCancelIconFgOver: cancelIconFgOver;
historySendBg: historyComposeAreaBg;
historySendBgOver: #f5f5f5 | historySendBg;
historyMenuItemBgOver: historySendBgOver;
historyTextInFg: windowTextFg;
historyTextOutFg: windowTextFg;

View file

@ -66,8 +66,7 @@ contactsBgOver: windowOverBg;
contactsNameFg: boxTextFg;
photoCropFadeBg: #0000007f;
photoCropPointFg: #ffffff7f;
settingsBg: windowBg;
settingsFixedBarBg: settingsBg;
settingsFixedBarBg: boxBg;
settingsCloseFg: cancelIconFg;
settingsCloseFgOver: cancelIconFgOver;
notificationsBoxMonitorFg: windowTextFg;
@ -78,13 +77,20 @@ notificationSampleNameFg: #939393; // windowSubTextFg;
introHeaderFg: windowTextFg;
introErrorFg: windowTextFg;
topBarBg: windowBg;
emojiPanBg: windowBg;
emojiPanCategories: #f7f7f7; // windowBg;
emojiPanHeaderFg: #999999; // windowSubTextFg;
emojiPanHeaderBg: #fffffff2; // emojiPanBg;
historyComposeAreaBg: windowBg;
historyComposeIconFg: #cccccc;
historyComposeIconFgOver: #bebebe;
historyPinnedBg: historyComposeAreaBg;
historyReplyBg: historyComposeAreaBg;
historyReplyCancelIconFg: cancelIconFg;
historyReplyCancelIconFgOver: cancelIconFgOver;
historySendBg: historyComposeAreaBg;
historySendBgOver: #f5f5f5; // historySendBg;
historyMenuItemBgOver: historySendBgOver;
historyTextInFg: windowTextFg;
historyTextOutFg: windowTextFg;
historyCaptionInFg: historyTextInFg;

View file

@ -157,7 +157,7 @@ contactsMultiSelect: MultiSelect {
iconBgOver: boxSearchCancelIconFgOver;
iconPosition: point(8px, 18px);
downIconPosition: point(8px, 18px);
iconPositionDown: point(8px, 18px);
}
fieldCancelSkip: 34px;
}
@ -230,13 +230,15 @@ sessionInfoFont: msgFont;
sessionInfoFg: #888888;
sessionTerminateTop: 30px;
sessionTerminateSkip: 18px;
sessionTerminate: IconButton(defaultIconButton) {
sessionTerminate: IconButton {
width: 16px;
height: 16px;
icon: simpleCloseIcon;
iconOver: simpleCloseIconOver;
iconPosition: point(3px, 3px);
downIconPosition: point(3px, 4px);
iconPositionDown: point(3px, 4px);
}
passcodeHeaderFont: font(19px);

View file

@ -289,7 +289,6 @@ void NotificationsBox::prepareNotificationSampleLarge() {
auto notifyTitle = st::msgNameFont->elided(qsl("Telegram Desktop"), rectForName.width());
p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
p.setOpacity(st::notifyClose.opacity);
st::notifyClose.icon.paint(p, w - st::notifyClosePos.x() - st::notifyClose.width + st::notifyClose.iconPosition.x(), st::notifyClosePos.y() + st::notifyClose.iconPosition.y(), w);
}

View file

@ -934,9 +934,13 @@ QByteArray iconMaskValueSize(int width, int height) {
return result;
}
QByteArray iconMaskValuePng(const QString &filepath) {
QByteArray iconMaskValuePng(QString filepath) {
QByteArray result;
auto inverted = filepath.endsWith("-invert");
if (inverted) {
filepath.chop(QLatin1String("-invert").size());
}
QImage png100x(filepath + ".png");
QImage png200x(filepath + "@2x.png");
png100x.setDevicePixelRatio(1.);
@ -957,6 +961,10 @@ QByteArray iconMaskValuePng(const QString &filepath) {
common::logError(kErrorBadIconSize, filepath + ".png") << "bad icons size, 1x: " << png100x.width() << "x" << png100x.height() << ", 2x: " << png200x.width() << "x" << png200x.height();
return result;
}
if (inverted) {
png100x.invertPixels();
png200x.invertPixels();
}
QImage png125x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 5), structure::data::pxAdjust(png100x.height(), 5), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
QImage png150x = png200x.scaled(structure::data::pxAdjust(png100x.width(), 6), structure::data::pxAdjust(png100x.height(), 6), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

View file

@ -822,16 +822,20 @@ QString ParsedFile::readMonoIconFilename() {
if (auto filename = readValue()) {
if (filename.type().tag == structure::TypeTag::String) {
auto filepath = QString::fromStdString(filename.String());
auto inverted = filepath.endsWith("-invert");
if (inverted) {
filepath.chop(QLatin1String("-invert").size());
}
for (const auto &path : options_.includePaths) {
QFileInfo fileinfo(path + '/' + filepath + ".png");
if (fileinfo.exists()) {
return path + '/' + filepath;
return path + '/' + filepath + (inverted ? "-invert" : "");
}
}
for (const auto &path : options_.includePaths) {
QFileInfo fileinfo(path + "/icons/" + filepath + ".png");
if (fileinfo.exists()) {
return path + "/icons/" + filepath;
return path + "/icons/" + filepath + (inverted ? "-invert" : "");
}
}
logError(common::kErrorFileNotFound) << "could not open icon file '" << filename.String() << "'";

View file

@ -84,18 +84,18 @@ dialogsTextStyleDraftActive: textStyle(dialogsTextStyle) {
}
dialogsNewChatIcon: icon {{ "dialogs_new_chat", #b7b7b7 }};
dialogsNewChatButton: IconButton(defaultIconButton) {
dialogsNewChatButton: IconButton {
width: 36px;
height: 36px;
icon: dialogsNewChatIcon;
iconPosition: point(9px, 10px);
downIconPosition: point(9px, 11px);
iconPositionDown: point(9px, 11px);
}
dialogsAddContact: IconButton(dialogsNewChatButton) {
icon: icon {{ "dialogs_add_contact", #a6a6a6 }};
iconPosition: point(8px, 8px);
downIconPosition: point(8px, 9px);
iconPositionDown: point(8px, 9px);
}
dialogsCancelSearch: IconButton(dialogsAddContact) {
icon: icon {{ "dialogs_cancel_search", #a6a6a6 }};

View file

@ -126,8 +126,8 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
p.fillRect(0, 0, w, st::mentionHeight, selected ? st::mentionBgOver : st::dialogsBg);
if (!paintingOther) {
if (selected) {
int skip = (st::mentionHeight - st::simpleCloseIcon.height()) / 2;
st::simpleCloseIcon.paint(p, QPoint(w - st::simpleCloseIcon.width() - skip, skip), width());
int skip = (st::mentionHeight - st::simpleCloseIconOver.height()) / 2;
st::simpleCloseIconOver.paint(p, QPoint(w - st::simpleCloseIconOver.width() - skip, skip), width());
}
QString first = (_hashtagFilter.size() < 2) ? QString() : ('#' + _hashtagResults.at(from).mid(0, _hashtagFilter.size() - 1)), second = (_hashtagFilter.size() < 2) ? ('#' + _hashtagResults.at(from)) : _hashtagResults.at(from).mid(_hashtagFilter.size() - 1);
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);

View file

@ -605,9 +605,9 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
bool selected = (i == _sel);
if (selected) {
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver);
int skip = (st::mentionHeight - st::simpleCloseIcon.height()) / 2;
int skip = (st::mentionHeight - st::simpleCloseIconOver.height()) / 2;
if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) {
st::simpleCloseIcon.paint(p, QPoint(width() - st::simpleCloseIcon.width() - skip, i * st::mentionHeight + skip), width());
st::simpleCloseIconOver.paint(p, QPoint(width() - st::simpleCloseIconOver.width() - skip, i * st::mentionHeight + skip), width());
}
}
if (!_mrows->isEmpty()) {

View file

@ -161,52 +161,73 @@ historyComposeField: flatTextarea {
historyComposeFieldMaxHeight: 224px;
// historyMinHeight: 56px;
historyMediaTypeFile: icon {{ "media_type_file", #b3b3b3, point(2px, 2px) }};
historyMediaTypePhoto: icon {{ "media_type_photo", #bebebe, point(2px, 2px) }};
historyMediaTypeVideo: icon {{ "media_type_video", #bebebe, point(2px, 2px) }};
historyMediaTypeSong: icon {{ "media_type_song", #bebebe, point(0px, 0px) }};
historyMediaTypeVoice: icon {{ "media_type_voice", #bebebe, point(2px, 2px) }};
historyMediaTypeLink: icon {{ "media_type_link", #bebebe, point(2px, 2px) }};
historyMediaTypeFile: icon {{ "media_type_file", historyComposeIconFg, point(2px, 2px) }};
historyMediaTypeFileOver: icon {{ "media_type_file", historyComposeIconFgOver, point(2px, 2px) }};
historyMediaTypePhoto: icon {{ "media_type_photo", historyComposeIconFg, point(2px, 2px) }};
historyMediaTypePhotoOver: icon {{ "media_type_photo", historyComposeIconFgOver, point(2px, 2px) }};
historyMediaTypeVideo: icon {{ "media_type_video", historyComposeIconFg, point(2px, 2px) }};
historyMediaTypeVideoOver: icon {{ "media_type_video", historyComposeIconFgOver, point(2px, 2px) }};
historyMediaTypeSong: icon {{ "media_type_song", historyComposeIconFg, point(0px, 0px) }};
historyMediaTypeSongOver: icon {{ "media_type_song", historyComposeIconFgOver, point(0px, 0px) }};
historyMediaTypeVoice: icon {{ "media_type_voice", historyComposeIconFg, point(2px, 2px) }};
historyMediaTypeVoiceOver: icon {{ "media_type_voice", historyComposeIconFgOver, point(2px, 2px) }};
historyMediaTypeLink: icon {{ "media_type_link", historyComposeIconFg, point(2px, 2px) }};
historyMediaTypeLinkOver: icon {{ "media_type_link", historyComposeIconFgOver, point(2px, 2px) }};
historyAttachDocument: IconButton(defaultIconButton) {
historyAttachDocument: IconButton {
width: 46px;
height: 46px;
icon: historyMediaTypeFile;
iconOver: historyMediaTypeFileOver;
iconPosition: point(9px, 9px);
downIconPosition: point(9px, 10px);
iconPositionDown: point(9px, 10px);
}
historyAttachPhoto: IconButton(historyAttachDocument) {
icon: historyMediaTypePhoto;
iconOver: historyMediaTypePhotoOver;
}
historyAttachEmoji: IconButton(historyAttachDocument) {
width: 33px;
icon: icon {{ "send_control_emoji", #b9b9b9 }};
icon: icon {{ "send_control_emoji", historyComposeIconFg }};
iconOver: icon {{ "send_control_emoji", historyComposeIconFgOver }};
iconPosition: point(12px, 16px);
downIconPosition: point(12px, 16px);
iconPositionDown: point(12px, 16px);
}
historyEmojiCircle: size(19px, 19px);
historyEmojiCirclePeriod: 1500;
historyEmojiCircleDuration: 500;
historyEmojiCircleTop: 13px;
historyEmojiCircleLine: 2px;
historyEmojiCircleFg: #b9b9b9;
historyEmojiCircleFg: historyComposeIconFg;
historyEmojiCircleFgOver: historyComposeIconFgOver;
historyEmojiCirclePart: 3.5;
historyBotKeyboardShow: IconButton(historyAttachEmoji) {
icon: icon {{ "send_control_bot_keyboard", #b3b3b3 }};
icon: icon {{ "send_control_bot_keyboard", historyComposeIconFg }};
iconOver: icon {{ "send_control_bot_keyboard", historyComposeIconFgOver }};
iconPosition: point(6px, 12px);
downIconPosition: point(6px, 12px);
iconPositionDown: point(6px, 12px);
}
historyBotKeyboardHide: IconButton(historyAttachEmoji) {
icon: icon {{ "send_control_bot_keyboard_hide", #b3b3b3 }};
icon: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFg }};
iconOver: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFgOver }};
iconPosition: point(5px, 17px);
downIconPosition: point(5px, 17px);
iconPositionDown: point(5px, 17px);
}
historyBotCommandStart: IconButton(historyBotKeyboardShow) {
icon: icon {{ "send_control_bot_command", #b3b3b3 }};
icon: icon {{ "send_control_bot_command", historyComposeIconFg }};
iconOver: icon {{ "send_control_bot_command", historyComposeIconFgOver }};
}
historyRecordVoice: icon {{ "send_control_record", #b9b9b9 }};
historyRecordVoiceActive: icon {{ "send_control_record", #58b2ed }};
historyRecordVoiceFg: historyComposeIconFg;
historyRecordVoiceFgOver: historyComposeIconFgOver;
historyRecordVoiceFgActive: #58b2ed;
historyRecordVoice: icon {{ "send_control_record", historyRecordVoiceFg }};
historyRecordVoiceOver: icon {{ "send_control_record", historyRecordVoiceFgOver }};
historyRecordVoiceActive: icon {{ "send_control_record", historyRecordVoiceFgActive }};
historyRecordSignalColor: #f17077;
historyRecordSignalMin: 5px;
historyRecordSignalMax: 12px;
@ -220,18 +241,18 @@ historyAttachDropdownMenu: DropdownMenu(defaultDropdownMenu) {
menu: Menu(defaultMenu) {
skip: 5px;
itemBgOver: historySendBgOver;
itemBgOver: historyMenuItemBgOver;
itemIconPosition: point(12px, 6px);
itemIconOpacity: 0.78;
itemIconOverOpacity: 1.;
itemPadding: margins(48px, 11px, 48px, 11px);
}
}
historySilentToggle: IconButton(historyBotKeyboardShow) {
icon: icon {{ "send_control_silent_off", #b3b3b3 }};
icon: icon {{ "send_control_silent_off", historyComposeIconFg }};
iconOver: icon {{ "send_control_silent_off", historyComposeIconFgOver }};
}
historySilentToggleOn: icon {{ "send_control_silent_on", #b3b3b3 }};
historySilentToggleOn: icon {{ "send_control_silent_on", historyComposeIconFg }};
historySilentToggleOnOver: icon {{ "send_control_silent_on", historyComposeIconFgOver }};
historyReplySkip: 51px;
historyReplyColor: #377aae;
@ -256,14 +277,16 @@ historyInlineBotCancel: MaskButton(historyReplyCancel) {
height: 46px;
}
topBarSearch: IconButton(defaultIconButton) {
topBarSearch: MaskButton {
width: 44px;
height: topBarHeight;
icon: icon {{ "title_search", #000000 }};
iconPosition: point(13px, 18px);
downIconPosition: point(13px, 18px);
bg: topBarBg;
icon: icon {{ "title_search-invert", topBarBg }};
opacity: 0.22;
overOpacity: 0.36;
iconBg: #c7c7c7;
iconBgOver: #a3a3a3;
iconPosition: point(13px, 18px);
iconPositionDown: point(13px, 18px);
}

View file

@ -2929,7 +2929,7 @@ void SilentToggle::mouseMoveEvent(QMouseEvent *e) {
void SilentToggle::setChecked(bool checked) {
if (_checked != checked) {
_checked = checked;
setIcon(_checked ? &st::historySilentToggleOn : nullptr);
setIcon(_checked ? &st::historySilentToggleOn : nullptr, _checked ? &st::historySilentToggleOnOver : nullptr);
}
}
@ -3134,8 +3134,8 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(_botKeyboardHide, SIGNAL(clicked()), this, SLOT(onKbToggle()));
connect(_botCommandStart, SIGNAL(clicked()), this, SLOT(onCmdStart()));
_attachType->addAction(lang(lng_attach_file), this, SLOT(onDocumentSelect()), &st::historyMediaTypeFile);
_attachType->addAction(lang(lng_attach_photo), this, SLOT(onPhotoSelect()), &st::historyMediaTypePhoto);
_attachType->addAction(lang(lng_attach_file), this, SLOT(onDocumentSelect()), &st::historyMediaTypeFile, &st::historyMediaTypeFileOver);
_attachType->addAction(lang(lng_attach_photo), this, SLOT(onPhotoSelect()), &st::historyMediaTypePhoto, &st::historyMediaTypePhotoOver);
_attachType->hide();
_emojiPan->hide();
_attachDragDocument->hide();
@ -3277,7 +3277,7 @@ void HistoryWidget::onTextChange() {
updateMouseTracking();
_a_record.stop();
_inRecord = _inField = false;
a_recordOver = a_recordDown = anim::fvalue(0, 0);
a_recordDown = anim::fvalue(0, 0);
a_recordCancel = anim::cvalue(st::historyRecordCancel->c, st::historyRecordCancel->c);
}
}
@ -4625,7 +4625,6 @@ void HistoryWidget::updateControlsVisibility() {
}
_a_record.stop();
_inRecord = _inField = false;
a_recordOver = anim::fvalue(0, 0);
}
if (_recording) {
_field.hide();
@ -5555,11 +5554,9 @@ void HistoryWidget::step_record(float64 ms, bool timer) {
float64 dt = ms / st::btnSend.duration;
if (dt >= 1 || !_send.isHidden() || isBotStart() || isBlocked()) {
_a_record.stop();
a_recordOver.finish();
a_recordDown.finish();
a_recordCancel.finish();
} else {
a_recordOver.update(dt, anim::linear);
a_recordDown.update(dt, anim::linear);
a_recordCancel.update(dt, anim::linear);
}
@ -5674,20 +5671,15 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
bool inField = pos.y() >= (_scroll.y() + _scroll.height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width();
bool inReplyEdit = QRect(st::historyReplySkip, _field.y() - st::sendPadding - st::historyReplyHeight, width() - st::historyReplySkip - _fieldBarCancel->width(), st::historyReplyHeight).contains(pos) && (_editMsgId || replyToId());
bool inPinnedMsg = QRect(0, 0, width(), st::historyReplyHeight).contains(pos) && _pinnedBar;
bool startAnim = false;
if (inRecord != _inRecord) {
_inRecord = inRecord;
a_recordOver.start(_inRecord ? 1 : 0);
a_recordDown.restart();
a_recordCancel.restart();
startAnim = true;
update(_send.geometry());
}
if (inField != _inField && _recording) {
_inField = inField;
a_recordOver.restart();
a_recordDown.start(_inField ? 1 : 0);
a_recordCancel.start(_inField ? st::historyRecordCancel->c : st::historyRecordCancelActive->c);
startAnim = true;
_a_record.start();
}
if (inReplyEdit != _inReplyEdit) {
_inReplyEdit = inReplyEdit;
@ -5697,7 +5689,6 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
_inPinnedMsg = inPinnedMsg;
setCursor(inPinnedMsg ? style::cur_pointer : style::cur_default);
}
if (startAnim) _a_record.start();
}
void HistoryWidget::leaveToChildEvent(QEvent *e, QWidget *child) { // e -- from enterEvent() of child TWidget
@ -5736,7 +5727,6 @@ void HistoryWidget::stopRecording(bool send) {
updateField();
a_recordDown.start(0);
a_recordOver.restart();
a_recordCancel = anim::cvalue(st::historyRecordCancel->c, st::historyRecordCancel->c);
_a_record.start();
}
@ -7435,7 +7425,6 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
updateField();
a_recordDown.start(1);
a_recordOver.restart();
_a_record.start();
} else if (_inReplyEdit) {
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
@ -8645,15 +8634,21 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
}
void HistoryWidget::drawRecordButton(Painter &p) {
if (a_recordDown.current() < 1) {
p.setOpacity(st::historyAttachEmoji.opacity * (1 - a_recordOver.current()) + st::historyAttachEmoji.overOpacity * a_recordOver.current());
st::historyRecordVoice.paint(p, _send.x() + (_send.width() - st::historyRecordVoice.width()) / 2, _send.y() + (_send.height() - st::historyRecordVoice.height()) / 2, width());
auto down = a_recordDown.current();
auto fastIcon = [down, this] {
if (down == 1.) {
return &st::historyRecordVoiceActive;
} else if (_inRecord) {
return &st::historyRecordVoiceOver;
}
return &st::historyRecordVoice;
};
fastIcon()->paintInCenter(p, _send.geometry());
if (down > 0. && down < 1.) {
p.setOpacity(down);
st::historyRecordVoiceActive.paintInCenter(p, _send.geometry());
p.setOpacity(1.);
}
if (a_recordDown.current() > 0) {
p.setOpacity(a_recordDown.current());
st::historyRecordVoiceActive.paint(p, _send.x() + (_send.width() - st::historyRecordVoiceActive.width()) / 2, _send.y() + (_send.height() - st::historyRecordVoiceActive.height()) / 2, width());
}
p.setOpacity(1);
}
void HistoryWidget::drawRecording(Painter &p) {

View file

@ -1118,7 +1118,6 @@ private:
bool _inPinnedMsg = false;
anim::ivalue a_recordingLevel = { 0, 0 };
int32 _recordingSamples = 0;
anim::fvalue a_recordOver = { 0, 0 };
anim::fvalue a_recordDown = { 0, 0 };
anim::cvalue a_recordCancel;
int32 _recordCancelWidth;

View file

@ -145,15 +145,20 @@ introErrorLabel: flatLabel(labelDefFlat) {
font: introErrorFont;
align: align(center);
}
introBackButton: IconButton(defaultIconButton) {
introBackButton: IconButton {
width: 40px;
height: 40px;
icon: icon {
{ size(40px, 40px), #f2f2f2 },
{ "title_previous", #adadad, point(12px, 12px) },
};
iconOver: icon {
{ size(40px, 40px), #eeeeee },
{ "title_previous", #969696, point(12px, 12px) },
};
iconPosition: point(0px, 0px);
downIconPosition: point(0px, 0px);
iconPositionDown: point(0px, 0px);
}
introBackPosition: point(32px, 32px);

View file

@ -1391,12 +1391,12 @@ void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
for (int32 i = 0; i < OverviewCount; ++i) {
if (mask & (1 << i)) {
switch (i) {
case OverviewPhotos: _mediaType->addAction(lang(lng_media_type_photos), this, SLOT(onPhotosSelect()), &st::historyMediaTypePhoto); break;
case OverviewVideos: _mediaType->addAction(lang(lng_media_type_videos), this, SLOT(onVideosSelect()), &st::historyMediaTypeVideo); break;
case OverviewMusicFiles: _mediaType->addAction(lang(lng_media_type_songs), this, SLOT(onSongsSelect()), &st::historyMediaTypeSong); break;
case OverviewFiles: _mediaType->addAction(lang(lng_media_type_files), this, SLOT(onDocumentsSelect()), &st::historyMediaTypeFile); break;
case OverviewVoiceFiles: _mediaType->addAction(lang(lng_media_type_audios), this, SLOT(onAudiosSelect()), &st::historyMediaTypeVoice); break;
case OverviewLinks: _mediaType->addAction(lang(lng_media_type_links), this, SLOT(onLinksSelect()), &st::historyMediaTypeLink); break;
case OverviewPhotos: _mediaType->addAction(lang(lng_media_type_photos), this, SLOT(onPhotosSelect()), &st::historyMediaTypePhoto, &st::historyMediaTypePhotoOver); break;
case OverviewVideos: _mediaType->addAction(lang(lng_media_type_videos), this, SLOT(onVideosSelect()), &st::historyMediaTypeVideo, &st::historyMediaTypeVideoOver); break;
case OverviewMusicFiles: _mediaType->addAction(lang(lng_media_type_songs), this, SLOT(onSongsSelect()), &st::historyMediaTypeSong, &st::historyMediaTypeSongOver); break;
case OverviewFiles: _mediaType->addAction(lang(lng_media_type_files), this, SLOT(onDocumentsSelect()), &st::historyMediaTypeFile, &st::historyMediaTypeFileOver); break;
case OverviewVoiceFiles: _mediaType->addAction(lang(lng_media_type_audios), this, SLOT(onAudiosSelect()), &st::historyMediaTypeVoice, &st::historyMediaTypeVoiceOver); break;
case OverviewLinks: _mediaType->addAction(lang(lng_media_type_links), this, SLOT(onLinksSelect()), &st::historyMediaTypeLink, &st::historyMediaTypeLinkOver); break;
}
}
}

View file

@ -72,16 +72,11 @@ mediaPlayerRepeatButton: IconButton {
width: 31px;
height: 30px;
opacity: 1.;
overOpacity: 1.;
icon: icon {
{ "player_repeat", mediaPlayerActiveFg, point(9px, 11px) }
};
iconPosition: point(0px, 0px);
downIconPosition: point(0px, 0px);
duration: 0;
iconPositionDown: point(0px, 0px);
}
mediaPlayerRepeatDisabledIcon: icon {
{ "player_repeat", #c8c8c8, point(9px, 11px)}
@ -106,14 +101,9 @@ mediaPlayerVolumeToggle: IconButton {
width: 31px;
height: 30px;
opacity: 1.;
overOpacity: 1.;
icon: mediaPlayerVolumeIcon0;
iconPosition: point(8px, 11px);
downIconPosition: point(8px, 11px);
duration: 0;
iconPositionDown: point(8px, 11px);
}
mediaPlayerVolumeMargin: 10px;
mediaPlayerVolumeSize: size(27px, 100px);
@ -219,10 +209,10 @@ mediaPlayerPanelPlayback: MediaSlider {
width: 3px;
activeFg: mediaPlayerActiveFg;
inactiveFg: mediaPlayerInactiveFg;
disabledActiveFg: mediaPlayerInactiveFg;
disabledInactiveFg: windowBg;
activeOpacity: 1.;
inactiveOpacity: 1.;
activeFgOver: mediaPlayerActiveFg;
inactiveFgOver: mediaPlayerInactiveFg;
activeFgDisabled: mediaPlayerInactiveFg;
inactiveFgDisabled: windowBg;
seekSize: size(9px, 9px);
duration: 150;
}

View file

@ -118,7 +118,7 @@ void Controller::updatePlayPauseResumeState(const AudioPlaybackState &playbackSt
_showPause = showPause;
connect(_playPauseResume, SIGNAL(clicked()), this, _showPause ? SIGNAL(pausePressed()) : SIGNAL(playPressed()));
_playPauseResume->setIcon(_showPause ? &st::mediaviewPauseIcon : nullptr);
_playPauseResume->setIcon(_showPause ? &st::mediaviewPauseIcon : nullptr, _showPause ? &st::mediaviewPauseIconOver : nullptr);
}
}
@ -169,7 +169,7 @@ void Controller::refreshTimeTexts() {
}
void Controller::setInFullScreen(bool inFullScreen) {
_fullScreenToggle->setIcon(inFullScreen ? &st::mediaviewFullScreenOutIcon : nullptr);
_fullScreenToggle->setIcon(inFullScreen ? &st::mediaviewFullScreenOutIcon : nullptr, inFullScreen ? &st::mediaviewFullScreenOutIconOver : nullptr);
disconnect(_fullScreenToggle, SIGNAL(clicked()), this, SIGNAL(toFullScreenPressed()));
disconnect(_fullScreenToggle, SIGNAL(clicked()), this, SIGNAL(fromFullScreenPressed()));

View file

@ -46,10 +46,16 @@ void VolumeController::paintEvent(QPaintEvent *e) {
int32 right = left + st::mediaviewVolumeIcon.width();
if (mid > left) {
auto over = _a_over.current(getms(), _over ? 1. : 0.);
p.setOpacity(over * st::mediaviewActiveOpacity + (1. - over) * st::mediaviewInactiveOpacity);
p.setClipRect(rtlrect(left, top, mid - left, st::mediaviewVolumeIcon.height(), width()));
st::mediaviewVolumeOnIcon.paint(p, QPoint(left, top), width());
auto over = _a_over.current(getms(), _over ? 1. : 0.);
if (over < 1.) {
st::mediaviewVolumeOnIcon.paint(p, QPoint(left, top), width());
}
if (over > 0.) {
p.setOpacity(over);
st::mediaviewVolumeOnIconOver.paint(p, QPoint(left, top), width());
p.setOpacity(1.);
}
}
if (right > mid) {
p.setClipRect(rtlrect(mid, top, right - mid, st::mediaviewVolumeIcon.height(), width()));

View file

@ -22,20 +22,19 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
using "basic.style";
using "ui/widgets/widgets.style";
mediaviewActiveOpacity: 1.;
mediaviewInactiveOpacity: 0.78;
mediaviewOverDuration: 150;
mediaviewPlaybackActive: #ffffff;
mediaviewPlaybackInactive: #474747;
mediaviewPlaybackActive: #c7c7c7;
mediaviewPlaybackInactive: #252525;
mediaviewPlaybackActiveOver: #ffffff;
mediaviewPlaybackInactiveOver: #474747;
mediaviewPlayback: MediaSlider {
width: 3px;
activeFg: mediaviewPlaybackActive;
inactiveFg: mediaviewPlaybackInactive;
disabledActiveFg: mediaviewPlaybackActive;
disabledInactiveFg: mediaviewPlaybackInactive;
activeOpacity: mediaviewActiveOpacity;
inactiveOpacity: mediaviewInactiveOpacity;
activeFgOver: mediaviewPlaybackActiveOver;
inactiveFgOver: mediaviewPlaybackInactiveOver;
activeFgDisabled: mediaviewPlaybackActive;
inactiveFgDisabled: mediaviewPlaybackInactive;
seekSize: size(11px, 11px);
duration: mediaviewOverDuration;
}
@ -50,32 +49,35 @@ mediaviewPlayButton: IconButton {
width: 25px;
height: 24px;
opacity: mediaviewInactiveOpacity;
overOpacity: mediaviewActiveOpacity;
icon: icon {{ "media_play", #c7c7c7, point(3px, 0px) }};
iconOver: icon {{ "media_play", #ffffff, point(3px, 0px) }};
icon: icon {{ "media_play", #ffffff, point(3px, 0px) }};
iconPosition: point(3px, 1px);
downIconPosition: point(3px, 1px);
iconPositionDown: point(3px, 1px);
duration: mediaviewOverDuration;
}
mediaviewPauseIcon: icon {{ "media_pause", #ffffff, point(1px, 1px) }};
mediaviewPauseIcon: icon {{ "media_pause", #c7c7c7, point(1px, 1px) }};
mediaviewPauseIconOver: icon {{ "media_pause", #ffffff, point(1px, 1px) }};
mediaviewPlayPauseLeft: 17px;
mediaviewFullScreenLeft: 17px;
mediaviewVolumeLeft: 15px;
mediaviewFullScreenButton: IconButton(mediaviewPlayButton) {
icon: icon {{ "media_fullscreen_to", #ffffff, point(0px, 0px) }};
icon: icon {{ "media_fullscreen_to", #c7c7c7, point(0px, 0px) }};
iconOver: icon {{ "media_fullscreen_to", #ffffff, point(0px, 0px) }};
iconPosition: point(0px, 1px);
downIconPosition: point(0px, 1px);
iconPositionDown: point(0px, 1px);
}
mediaviewFullScreenOutIcon: icon {{ "media_fullscreen_from", #ffffff, point(0px, 0px) }};
mediaviewFullScreenOutIcon: icon {{ "media_fullscreen_from", #c7c7c7, point(0px, 0px) }};
mediaviewFullScreenOutIconOver: icon {{ "media_fullscreen_from", #ffffff, point(0px, 0px) }};
mediaviewPlaybackTop: 28px;
mediaviewVolumeSize: size(44px, 20px);
mediaviewVolumeIcon: icon {{ "media_volume", mediaviewPlaybackInactive, point(0px, 0px) }};
mediaviewVolumeIcon: icon {{ "media_volume", mediaviewPlaybackInactiveOver, point(0px, 0px) }};
mediaviewVolumeOnIcon: icon {{ "media_volume", mediaviewPlaybackActive, point(0px, 0px) }};
mediaviewVolumeOnIconOver: icon {{ "media_volume", mediaviewPlaybackActiveOver, point(0px, 0px) }};
mediaviewVolumeIconTop: 8px;
mediaviewControllerRadius: 25px;

View file

@ -79,7 +79,7 @@ settingsEditButton: IconButton(dialogsNewChatButton) {
height: 34px;
iconPosition: point(3px, 9px);
downIconPosition: point(3px, 10px);
iconPositionDown: point(3px, 10px);
}
settingsBlocksTop: 7px;

View file

@ -198,7 +198,7 @@ void Widget::showDone() {
void Widget::paintEvent(QPaintEvent *e) {
Painter p(this);
p.fillRect(e->rect(), st::settingsBg);
p.fillRect(e->rect(), st::boxBg);
}
void Widget::resizeEvent(QResizeEvent *e) {

View file

@ -2489,10 +2489,10 @@ void EmojiPanel::paintEvent(QPaintEvent *e) {
Painter p(this);
if (!_deleteVisible) {
p.fillRect(0, 0, width(), st::emojiPanHeader, st::emojiPanHeaderBg->b);
p.fillRect(0, 0, width(), st::emojiPanHeader, st::emojiPanHeaderBg);
}
p.setFont(st::emojiPanHeaderFont);
p.setPen(st::emojiPanHeaderColor);
p.setPen(st::emojiPanHeaderFg);
p.drawTextLeft(st::emojiPanHeaderLeft, st::emojiPanHeaderTop, width(), _text);
}

View file

@ -105,13 +105,8 @@ emojiCategory: IconButton {
width: 42px;
height: 46px;
opacity: 1.;
overOpacity: 1.;
iconPosition: point(11px, 12px);
downIconPosition: point(11px, 12px);
duration: 0;
iconPositionDown: point(11px, 12px);
}
emojiCategoryRecent: IconButton(emojiCategory) { icon: emojiRecent; }
emojiCategoryPeople: IconButton(emojiCategory) { icon: emojiPeople; }
@ -131,10 +126,8 @@ emojiPanHover: #f0f4f7;
emojiPanHeader: 42px;
emojiPanHeaderFont: semiboldFont;
emojiPanHeaderColor: #999999;
emojiPanHeaderLeft: 22px;
emojiPanHeaderTop: 12px;
emojiPanHeaderBg: #fffffff2;
emojiColorsPadding: 5px;
emojiColorsSep: 1px;
@ -162,11 +155,13 @@ stickerPreviewDuration: 150;
stickerPreviewBg: #FFFFFFB0;
stickerPreviewMin: 0.1;
hashtagClose: IconButton(defaultIconButton) {
hashtagClose: IconButton {
width: 30px;
height: 30px;
icon: simpleCloseIcon;
iconOver: simpleCloseIconOver;
iconPosition: point(10px, 10px);
downIconPosition: point(10px, 11px);
iconPositionDown: point(10px, 11px);
}

View file

@ -219,14 +219,14 @@ namespace anim {
using ValueType = QColor;
cvalue() = default;
cvalue(const QColor &from)
explicit cvalue(QColor from)
: _cur(from)
, _from_r(from.redF())
, _from_g(from.greenF())
, _from_b(from.blueF())
, _from_a(from.alphaF()) {
}
cvalue(const QColor &from, const QColor &to)
cvalue(QColor from, QColor to)
: _cur(from)
, _from_r(from.redF())
, _from_g(from.greenF())
@ -237,7 +237,7 @@ namespace anim {
, _delta_b(to.blueF() - from.blueF())
, _delta_a(to.alphaF() - from.alphaF()) {
}
void start(const QColor &to) {
void start(QColor to) {
_from_r = _cur.redF();
_from_g = _cur.greenF();
_from_b = _cur.blueF();
@ -265,7 +265,7 @@ namespace anim {
result.setAlphaF(_from_a);
return result;
}
const QColor &current() const {
QColor current() const {
return _cur;
}
QColor to() const {

View file

@ -27,7 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
HistoryDownButton::HistoryDownButton(QWidget *parent) : Button(parent)
, a_arrowOpacity(st::historyAttachEmoji.opacity, st::historyAttachEmoji.opacity)
//, a_arrowOpacity(st::historyAttachEmoji.opacity, st::historyAttachEmoji.opacity)
, _a_arrowOver(animation(this, &HistoryDownButton::step_arrowOver)) {
setCursor(style::cur_pointer);
@ -53,10 +53,8 @@ HistoryDownButton::HistoryDownButton(QWidget *parent) : Button(parent)
void HistoryDownButton::paintEvent(QPaintEvent *e) {
Painter p(this);
float64 opacity = 1.;
if (_a_show.animating(getms())) {
opacity = _a_show.current();
p.setOpacity(opacity);
p.setOpacity(_a_show.current());
p.drawPixmap(0, st::historyToDownPaddingTop, _cache);
} else if (!_shown) {
hide();
@ -64,10 +62,8 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) {
} else {
st::historyToDown.paint(p, QPoint(0, st::historyToDownPaddingTop), width());
}
p.setOpacity(opacity * a_arrowOpacity.current());
st::historyToDownArrow.paint(p, QPoint(0, st::historyToDownPaddingTop), width());
if (_unreadCount > 0) {
p.setOpacity(opacity);
auto unreadString = QString::number(_unreadCount);
if (unreadString.size() > 4) {
unreadString = qsl("..") + unreadString.mid(unreadString.size() - 4);
@ -83,7 +79,7 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) {
}
void HistoryDownButton::onStateChanged(int oldState, ButtonStateChangeSource source) {
a_arrowOpacity.start((_state & (StateOver | StateDown)) ? st::historyAttachEmoji.overOpacity : st::historyAttachEmoji.opacity);
//a_arrowOpacity.start((_state & (StateOver | StateDown)) ? st::historyAttachEmoji.overOpacity : st::historyAttachEmoji.opacity);
if (source == ButtonByUser || source == ButtonByPress) {
_a_arrowOver.stop();
@ -151,16 +147,15 @@ void EmojiButton::paintEvent(QPaintEvent *e) {
p.fillRect(e->rect(), st::historyComposeAreaBg);
auto over = _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
auto opacity = over * _st.overOpacity + (1. - over) * _st.opacity;
auto loading = a_loading.current(ms, _loading ? 1 : 0);
p.setOpacity(opacity * (1 - loading));
p.setOpacity(1 - loading);
_st.icon.paint(p, (_state & StateDown) ? _st.downIconPosition : _st.iconPosition, width());
auto over = (_state & StateOver);
auto icon = &(over ? _st.iconOver : _st.icon);
icon->paint(p, (_state & StateDown) ? _st.iconPositionDown : _st.iconPosition, width());
p.setOpacity(opacity);
p.setPen(QPen(st::historyEmojiCircleFg, st::historyEmojiCircleLine));
p.setOpacity(1.);
p.setPen(QPen(over ? st::historyEmojiCircleFgOver : st::historyEmojiCircleFg, st::historyEmojiCircleLine));
p.setBrush(Qt::NoBrush);
p.setRenderHint(QPainter::HighQualityAntialiasing);
@ -191,9 +186,7 @@ void EmojiButton::setLoading(bool loading) {
void EmojiButton::onStateChanged(int oldState, ButtonStateChangeSource source) {
auto over = (_state & StateOver);
if (over != (oldState & StateOver)) {
auto from = over ? 0. : 1.;
auto to = over ? 1. : 0.;
_a_over.start([this] { update(); }, from, to, _st.duration);
update();
}
}

View file

@ -75,8 +75,6 @@ protected:
private:
const style::IconButton &_st;
FloatAnimation _a_over;
bool _loading = false;
FloatAnimation a_loading;
Animation _a_loading;

View file

@ -29,8 +29,9 @@ IconButton::IconButton(QWidget *parent, const style::IconButton &st) : Button(pa
setCursor(style::cur_pointer);
}
void IconButton::setIcon(const style::icon *icon) {
void IconButton::setIcon(const style::icon *icon, const style::icon *iconOver) {
_iconOverride = icon;
_iconOverrideOver = iconOver;
update();
}
@ -38,22 +39,47 @@ void IconButton::paintEvent(QPaintEvent *e) {
Painter p(this);
auto over = _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
p.setOpacity(over * _st.overOpacity + (1. - over) * _st.opacity);
auto icon = (_iconOverride ? _iconOverride : &_st.icon);
auto position = (_state & StateDown) ? _st.downIconPosition : _st.iconPosition;
auto overIcon = [this] {
if (_iconOverrideOver) {
return _iconOverrideOver;
} else if (!_st.iconOver.empty()) {
return &_st.iconOver;
} else if (_iconOverride) {
return _iconOverride;
}
return &_st.icon;
};
auto justIcon = [this] {
if (_iconOverride) {
return _iconOverride;
}
return &_st.icon;
};
auto icon = (over == 1.) ? overIcon() : justIcon();
auto position = (_state & StateDown) ? _st.iconPositionDown : _st.iconPosition;
if (position.x() < 0) {
position.setX((width() - icon->width()) / 2);
}
icon->paint(p, position, width());
if (over > 0. && over < 1.) {
auto iconOver = overIcon();
if (iconOver != icon) {
p.setOpacity(over);
iconOver->paint(p, position, width());
}
}
}
void IconButton::onStateChanged(int oldState, ButtonStateChangeSource source) {
auto over = (_state & StateOver);
if (over != (oldState & StateOver)) {
auto from = over ? 0. : 1.;
auto to = over ? 1. : 0.;
_a_over.start([this] { update(); }, from, to, _st.duration);
if (_st.duration) {
auto from = over ? 0. : 1.;
auto to = over ? 1. : 0.;
_a_over.start([this] { update(); }, from, to, _st.duration);
} else {
update();
}
}
}
@ -77,7 +103,7 @@ void MaskButton::paintEvent(QPaintEvent *e) {
Painter p(this);
auto clip = e->rect();
auto position = (_state & StateDown) ? _st.downIconPosition : _st.iconPosition;
auto position = (_state & StateDown) ? _st.iconPositionDown : _st.iconPosition;
if (position.x() < 0) {
position.setX((width() - _st.icon.width()) / 2);
}

View file

@ -30,7 +30,7 @@ public:
IconButton(QWidget *parent, const style::IconButton &st);
// Pass nullptr to restore the default icon.
void setIcon(const style::icon *icon);
void setIcon(const style::icon *icon, const style::icon *iconOver = nullptr);
protected:
void paintEvent(QPaintEvent *e) override;
@ -40,6 +40,7 @@ protected:
private:
const style::IconButton &_st;
const style::icon *_iconOverride = nullptr;
const style::icon *_iconOverrideOver = nullptr;
FloatAnimation _a_over;

View file

@ -75,34 +75,58 @@ void stopManager() {
internal::destroyIcons();
}
QImage colorizeImage(const QImage &src, const color &c, const QRect &r) {
QImage colorizeImage(const QImage &src, QColor color, const QRect &r) {
t_assert(r.x() >= 0 && src.width() >= r.x() + r.width());
t_assert(r.y() >= 0 && src.height() >= r.y() + r.height());
int a = c->c.alpha() + 1;
int fg_r = c->c.red() * a, fg_g = c->c.green() * a, fg_b = c->c.blue() * a, fg_a = 255 * a;
auto initialAlpha = color.alpha() + 1;
auto red = color.red() * initialAlpha;
auto green = color.green() * initialAlpha;
auto blue = color.blue() * initialAlpha;
auto alpha = 255 * initialAlpha;
auto alpha_red = static_cast<uint64>(alpha) | (static_cast<uint64>(red) << 32);
auto green_blue = static_cast<uint64>(green) | (static_cast<uint64>(blue) << 32);
QImage result(r.width(), r.height(), QImage::Format_ARGB32_Premultiplied);
auto bits = result.bits();
auto maskbits = src.constBits();
int bpp = result.depth(), maskbpp = src.depth();
int bpl = result.bytesPerLine(), maskbpl = src.bytesPerLine();
for (int x = 0, xoffset = r.x(); x < r.width(); ++x) {
for (int y = 0, yoffset = r.y(); y < r.height(); ++y) {
int s = y * bpl + ((x * bpp) >> 3);
int o = maskbits[(y + yoffset) * maskbpl + (((x + xoffset) * maskbpp) >> 3)] + 1;
bits[s + 0] = (fg_b * o) >> 16;
bits[s + 1] = (fg_g * o) >> 16;
bits[s + 2] = (fg_r * o) >> 16;
bits[s + 3] = (fg_a * o) >> 16;
auto result = QImage(r.width(), r.height(), QImage::Format_ARGB32_Premultiplied);
auto resultBytesPerPixel = (src.depth() >> 3);
auto resultIntsPerPixel = 1;
auto resultIntsPerLine = (result.bytesPerLine() >> 2);
auto resultIntsAdded = resultIntsPerLine - r.width() * resultIntsPerPixel;
auto resultInts = reinterpret_cast<uint32*>(result.bits());
t_assert(resultIntsAdded >= 0);
t_assert(result.depth() == ((resultIntsPerPixel * sizeof(uint32)) << 3));
t_assert(result.bytesPerLine() == (resultIntsPerLine << 2));
auto maskBytesPerPixel = (src.depth() >> 3);
auto maskBytesPerLine = src.bytesPerLine();
auto maskBytesAdded = maskBytesPerLine - r.width() * maskBytesPerPixel;
auto maskBytes = src.constBits() + r.y() * maskBytesPerLine + r.x() * maskBytesPerPixel;
t_assert(maskBytesAdded >= 0);
t_assert(src.depth() == (maskBytesPerPixel << 3));
for (int y = 0; y != r.height(); ++y) {
for (int x = 0; x != r.width(); ++x) {
auto maskOpacity = static_cast<uint64>(*maskBytes) + 1;
auto alpha_red_masked = (alpha_red * maskOpacity) >> 16;
auto green_blue_masked = (green_blue * maskOpacity) >> 16;
auto alpha = static_cast<uint32>(alpha_red_masked & 0xFF);
auto red = static_cast<uint32>((alpha_red_masked >> 32) & 0xFF);
auto green = static_cast<uint32>(green_blue_masked & 0xFF);
auto blue = static_cast<uint32>((green_blue_masked >> 32) & 0xFF);
*resultInts = blue | (green << 8) | (red << 16) | (alpha << 24);
maskBytes += maskBytesPerPixel;
resultInts += resultIntsPerPixel;
}
maskBytes += maskBytesAdded;
resultInts += resultIntsAdded;
}
return result;
result.setDevicePixelRatio(src.devicePixelRatio());
return std_::move(result);
}
namespace internal {
QImage createCircleMask(int size, const QColor &bg, const QColor &fg) {
QImage createCircleMask(int size, QColor bg, QColor fg) {
int realSize = size * cIntRetinaFactor();
#ifndef OS_MAC_OLD
auto result = QImage(realSize, realSize, QImage::Format::Format_Grayscale8);

View file

@ -63,11 +63,15 @@ bool setPaletteColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);
void startManager();
void stopManager();
QImage colorizeImage(const QImage &src, const color &c, const QRect &r);
QImage colorizeImage(const QImage &src, QColor c, const QRect &r);
inline QImage colorizeImage(const QImage &src, const color &c, const QRect &r) {
return colorizeImage(src, c->c, r);
}
namespace internal {
QImage createCircleMask(int size, const QColor &bg, const QColor &fg);
QImage createCircleMask(int size, QColor bg, QColor fg);
} // namespace internal

View file

@ -44,7 +44,7 @@ void destroyColors() {
Color::Color(const Color &c) : ptr(c.owner ? new ColorData(*c.ptr) : c.ptr), owner(c.owner) {
}
Color::Color(const QColor &c) : owner(false) {
Color::Color(QColor c) : owner(false) {
init(c.red(), c.green(), c.blue(), c.alpha());
}
@ -81,7 +81,7 @@ Color::~Color() {
ColorData::ColorData(uchar r, uchar g, uchar b, uchar a) : c(int(r), int(g), int(b), int(a)), p(c), b(c) {
}
void ColorData::set(const QColor &color) {
void ColorData::set(QColor color) {
c = color;
p = QPen(color);
b = QBrush(color);

View file

@ -31,12 +31,12 @@ public:
Color(Qt::Initialization = Qt::Uninitialized) {
}
Color(const Color &c);
explicit Color(const QColor &c);
explicit Color(QColor c);
Color(uchar r, uchar g, uchar b, uchar a = 255);
Color &operator=(const Color &c);
~Color();
void set(const QColor &newv);
void set(QColor newv);
void set(uchar r, uchar g, uchar b, uchar a = 255);
operator const QBrush &() const;
@ -79,7 +79,7 @@ public:
private:
ColorData(uchar r, uchar g, uchar b, uchar a);
void set(const QColor &c);
void set(QColor c);
friend class Color;
@ -102,12 +102,26 @@ inline Color::operator const QPen &() const {
} // namespace internal
inline QColor interpolate(QColor a, QColor b, float64 opacity_b) {
auto bOpacity = static_cast<int>(opacity_b * 255), aOpacity = (255 - bOpacity);
return {
(a.red() * aOpacity + b.red() * bOpacity + 1) >> 8,
(a.green() * aOpacity + b.green() * bOpacity + 1) >> 8,
(a.blue() * aOpacity + b.blue() * bOpacity + 1) >> 8,
(a.alpha() * aOpacity + b.alpha() * bOpacity + 1) >> 8
};
}
inline QColor interpolate(const style::internal::Color &a, QColor b, float64 opacity_b) {
return interpolate(a->c, b, opacity_b);
}
inline QColor interpolate(QColor a, const style::internal::Color &b, float64 opacity_b) {
return interpolate(a, b->c, opacity_b);
}
inline QColor interpolate(const style::internal::Color &a, const style::internal::Color &b, float64 opacity_b) {
QColor result;
result.setRedF((a->c.redF() * (1. - opacity_b)) + (b->c.redF() * opacity_b));
result.setGreenF((a->c.greenF() * (1. - opacity_b)) + (b->c.greenF() * opacity_b));
result.setBlueF((a->c.blueF() * (1. - opacity_b)) + (b->c.blueF() * opacity_b));
return result;
return interpolate(a->c, b->c, opacity_b);
}
} // namespace style

View file

@ -25,11 +25,13 @@ namespace style {
namespace internal {
namespace {
uint32 colorKey(const QColor &c) {
uint32 colorKey(QColor c) {
return (((((uint32(c.red()) << 8) | uint32(c.green())) << 8) | uint32(c.blue())) << 8) | uint32(c.alpha());
}
using IconMasks = QMap<const IconMask*, QImage>;
using IconPixmaps = QMap<QPair<const IconMask*, uint32>, QPixmap>;
NeverFreedPointer<IconMasks> iconMasks;
NeverFreedPointer<IconPixmaps> iconPixmaps;
inline int pxAdjust(int value, int scale) {
@ -39,8 +41,9 @@ inline int pxAdjust(int value, int scale) {
return qFloor((value * scale / 4.) + 0.1);
}
QPixmap createIconPixmap(const IconMask *mask, const Color &color) {
QImage createIconMask(const IconMask *mask) {
auto maskImage = QImage::fromData(mask->data(), mask->size(), "PNG");
maskImage.setDevicePixelRatio(cRetinaFactor());
t_assert(!maskImage.isNull());
// images are layouted like this:
@ -64,9 +67,11 @@ QPixmap createIconPixmap(const IconMask *mask, const Color &color) {
}
}
}
auto finalImage = colorizeImage(maskImage, color, r);
finalImage.setDevicePixelRatio(cRetinaFactor());
return App::pixmapFromImageInPlace(std_::move(finalImage));
return maskImage.copy(r);
}
QImage createIconImage(const QImage &mask, QColor color) {
return colorizeImage(mask, color, QRect(0, 0, mask.width(), mask.height()));
}
} // namespace
@ -119,6 +124,29 @@ void MonoIcon::fill(QPainter &p, const QRect &rect) const {
}
}
void MonoIcon::paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const {
int w = width(), h = height();
QPoint fullOffset = pos + offset();
int partPosX = rtl() ? (outerw - fullOffset.x() - w) : fullOffset.x();
int partPosY = fullOffset.y();
ensureLoaded();
if (_pixmap.isNull()) {
p.fillRect(partPosX, partPosY, w, h, colorOverride);
} else {
p.drawImage(partPosX, partPosY, createIconImage(_maskImage, colorOverride));
}
}
void MonoIcon::fill(QPainter &p, const QRect &rect, QColor colorOverride) const {
ensureLoaded();
if (_pixmap.isNull()) {
p.fillRect(rect, colorOverride);
} else {
p.drawImage(rect, createIconImage(_maskImage, colorOverride), QRect(0, 0, _pixmap.width(), _pixmap.height()));
}
}
void MonoIcon::ensureLoaded() const {
if (_size.isValid()) {
return;
@ -155,34 +183,24 @@ void MonoIcon::ensureLoaded() const {
t_assert(!"Bad data in generated icon!");
}
} else {
if (_owningPixmap) {
_pixmap = createIconPixmap(_mask, _color);
} else {
iconPixmaps.createIfNull();
auto key = qMakePair(_mask, colorKey(_color->c));
auto i = iconPixmaps->constFind(key);
if (i == iconPixmaps->cend()) {
i = iconPixmaps->insert(key, createIconPixmap(_mask, _color));
}
_pixmap = i.value();
iconMasks.createIfNull();
auto i = iconMasks->constFind(_mask);
if (i == iconMasks->cend()) {
i = iconMasks->insert(_mask, createIconMask(_mask));
}
_maskImage = i.value();
iconPixmaps.createIfNull();
auto key = qMakePair(_mask, colorKey(_color->c));
auto j = iconPixmaps->constFind(key);
if (j == iconPixmaps->cend()) {
j = iconPixmaps->insert(key, App::pixmapFromImageInPlace(createIconImage(_maskImage, _color->c)));
}
_pixmap = j.value();
_size = _pixmap.size() / cIntRetinaFactor();
}
}
MonoIcon::MonoIcon(const IconMask *mask, const Color &color, QPoint offset, OwningPixmapTag)
: _mask(mask)
, _color(color)
, _offset(offset)
, _owningPixmap(true) {
}
void Icon::paint(QPainter &p, const QPoint &pos, int outerw) const {
for_const (auto &part, _parts) {
part.paint(p, pos, outerw);
}
}
void Icon::fill(QPainter &p, const QRect &rect) const {
if (_parts.isEmpty()) return;
@ -194,6 +212,17 @@ void Icon::fill(QPainter &p, const QRect &rect) const {
}
}
void Icon::fill(QPainter &p, const QRect &rect, QColor colorOverride) const {
if (_parts.isEmpty()) return;
auto partSize = _parts.at(0).size();
for_const (auto &part, _parts) {
t_assert(part.offset() == QPoint(0, 0));
t_assert(part.size() == partSize);
part.fill(p, rect, colorOverride);
}
}
int Icon::width() const {
if (_width < 0) {
_width = 0;
@ -216,6 +245,7 @@ int Icon::height() const {
void destroyIcons() {
iconPixmaps.clear();
iconMasks.clear();
}
} // namespace internal

View file

@ -55,45 +55,31 @@ public:
QSize size() const;
QPoint offset() const;
void paint(QPainter &p, const QPoint &pos, int outerw) const;
void fill(QPainter &p, const QRect &rect) const;
MonoIcon clone(const Color &color) const {
return MonoIcon(_mask, color ? color : _color, _offset, OwningPixmapTag());
}
void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const;
void fill(QPainter &p, const QRect &rect, QColor colorOverride) const;
~MonoIcon() {
}
private:
struct OwningPixmapTag {
};
MonoIcon(const IconMask *mask, const Color &color, QPoint offset, OwningPixmapTag);
void ensureLoaded() const;
const IconMask *_mask = nullptr;
Color _color;
QPoint _offset = { 0, 0 };
mutable QImage _maskImage;
mutable QPixmap _pixmap; // for pixmaps
mutable QSize _size; // for rects
bool _owningPixmap = false;
};
class Icon {
struct ColoredCopy;
public:
Icon(Qt::Initialization) {
}
Icon(const ColoredCopy &makeCopy) {
_parts.reserve(makeCopy.copyFrom._parts.size());
auto colorIt = makeCopy.colors.cbegin(), colorsEnd = makeCopy.colors.cend();
for_const (auto &part, makeCopy.copyFrom._parts) {
auto newPart = part.clone((colorIt == colorsEnd) ? Color(Qt::Uninitialized) : *(colorIt++));
_parts.push_back(newPart);
}
}
template <typename ... MonoIcons>
Icon(const MonoIcons&... icons) {
@ -101,14 +87,15 @@ public:
addIcons(icons...);
}
std_::unique_ptr<Icon> clone(const QVector<Color> &colors) {
return std_::make_unique<Icon>(ColoredCopy { *this, colors });
}
bool empty() const {
return _parts.empty();
}
void paint(QPainter &p, const QPoint &pos, int outerw) const;
void paint(QPainter &p, const QPoint &pos, int outerw) const {
for_const (auto &part, _parts) {
part.paint(p, pos, outerw);
}
}
void paint(QPainter &p, int x, int y, int outerw) const {
paint(p, QPoint(x, y), outerw);
}
@ -116,6 +103,20 @@ public:
paint(p, outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2, outer.x() * 2 + outer.width());
}
void fill(QPainter &p, const QRect &rect) const;
void paint(QPainter &p, const QPoint &pos, int outerw, QColor colorOverride) const {
for_const (auto &part, _parts) {
part.paint(p, pos, outerw, colorOverride);
}
}
void paint(QPainter &p, int x, int y, int outerw, QColor colorOverride) const {
paint(p, QPoint(x, y), outerw, colorOverride);
}
void paintInCenter(QPainter &p, const QRect &outer, QColor colorOverride) const {
paint(p, outer.x() + (outer.width() - width()) / 2, outer.y() + (outer.height() - height()) / 2, outer.x() * 2 + outer.width(), colorOverride);
}
void fill(QPainter &p, const QRect &rect, QColor colorOverride) const;
int width() const;
int height() const;
QSize size() const {
@ -123,11 +124,6 @@ public:
}
private:
struct ColoredCopy {
const Icon &copyFrom;
const QVector<Color> &colors;
};
template <typename ... MonoIcons>
void addIcons() {
}

View file

@ -64,8 +64,8 @@ void DropdownMenu::init() {
hide();
}
QAction *DropdownMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon) {
return _menu->addAction(text, receiver, member, icon);
QAction *DropdownMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, receiver, member, icon, iconOver);
}
QAction *DropdownMenu::addSeparator() {

View file

@ -30,7 +30,7 @@ class DropdownMenu : public InnerDropdown {
public:
DropdownMenu(QWidget *parent, const style::DropdownMenu &st = st::defaultDropdownMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
void clearActions();

View file

@ -43,10 +43,10 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
Painter p(this);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.setOpacity(fadeOpacity());
auto horizontal = isHorizontal();
auto ms = getms();
auto masterOpacity = fadeOpacity();
auto radius = _st.width / 2;
auto disabled = isDisabled();
auto over = getCurrentOverFactor(ms);
@ -62,16 +62,21 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
auto length = _alwaysDisplayMarker ? (horizontal ? width() : height()) : markerLength;
auto mid = qRound(from + value * length);
auto end = from + length;
auto &activeFg = disabled ? _st.disabledActiveFg : _st.activeFg;
auto &inactiveFg = disabled ? _st.disabledInactiveFg : _st.inactiveFg;
auto activeFg = disabled ? &_st.activeFgDisabled : (over == 1. ? &_st.activeFgOver : (over == 0. ? &_st.activeFg : nullptr));
auto inactiveFg = disabled ? &_st.inactiveFgDisabled : (over == 1. ? &_st.inactiveFgOver : (over == 0. ? &_st.inactiveFg : nullptr));
auto activeFgOver = activeFg ? QColor() : style::interpolate(_st.activeFg, _st.activeFgOver, over);
auto inactiveFgOver = inactiveFg ? QColor() : style::interpolate(_st.inactiveFg, _st.inactiveFgOver, over);
if (mid > from) {
auto fromClipRect = horizontal ? QRect(0, 0, mid, height()) : QRect(0, 0, width(), mid);
auto fromRect = horizontal
? QRect(from, (height() - _st.width) / 2, mid + radius - from, _st.width)
: QRect((width() - _st.width) / 2, from, _st.width, mid + radius - from);
p.setClipRect(fromClipRect);
p.setOpacity(masterOpacity * (over * _st.activeOpacity + (1. - over) * _st.inactiveOpacity));
p.setBrush(horizontal ? activeFg : inactiveFg);
if (auto brush = (horizontal ? activeFg : inactiveFg)) {
p.setBrush(*brush);
} else {
p.setBrush(horizontal ? activeFgOver : inactiveFgOver);
}
p.drawRoundedRect(fromRect, radius, radius);
}
if (end > mid) {
@ -80,8 +85,11 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
? QRect(mid - radius, (height() - _st.width) / 2, end - (mid - radius), _st.width)
: QRect((width() - _st.width) / 2, mid - radius, _st.width, end - (mid - radius));
p.setClipRect(endClipRect);
p.setOpacity(masterOpacity);
p.setBrush(horizontal ? inactiveFg : activeFg);
if (auto brush = (horizontal ? inactiveFg : activeFg)) {
p.setBrush(*brush);
} else {
p.setBrush(horizontal ? inactiveFgOver : activeFgOver);
}
p.drawRoundedRect(endRect, radius, radius);
}
auto markerSizeRatio = disabled ? 0. : (_alwaysDisplayMarker ? 1. : over);
@ -94,8 +102,11 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
auto remove = static_cast<int>(((1. - markerSizeRatio) * size) / 2.);
if (remove * 2 < size) {
p.setClipRect(rect());
p.setOpacity(masterOpacity * _st.activeOpacity);
p.setBrush(activeFg);
if (activeFg) {
p.setBrush(*activeFg);
} else {
p.setBrush(activeFgOver);
}
p.drawEllipse(seekButton.marginsRemoved(QMargins(remove, remove, remove, remove)));
}
}

View file

@ -49,18 +49,19 @@ void Menu::init() {
setAttribute(Qt::WA_OpaquePaintEvent);
}
QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon) {
QAction *Menu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
auto action = new QAction(text, this);
connect(action, SIGNAL(triggered(bool)), receiver, member, Qt::QueuedConnection);
return addAction(action, icon);
return addAction(action, icon, iconOver);
}
QAction *Menu::addAction(QAction *action, const style::icon *icon) {
QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) {
connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
_actions.push_back(action);
ActionData data;
data.icon = icon;
data.iconOver = iconOver ? iconOver : icon;
data.hasSubmenu = (action->menu() != nullptr);
_actionsData.push_back(data);
@ -167,10 +168,8 @@ void Menu::paintEvent(QPaintEvent *e) {
} else {
auto enabled = action->isEnabled(), selected = (i == _selected && enabled);
p.fillRect(0, 0, width(), actionHeight, selected ? _st.itemBgOver : _st.itemBg);
if (data.icon) {
p.setOpacity(selected ? _st.itemIconOverOpacity : _st.itemIconOpacity);
data.icon->paint(p, _st.itemIconPosition, width());
p.setOpacity(1.);
if (auto icon = (selected ? data.iconOver : data.icon)) {
icon->paint(p, _st.itemIconPosition, width());
}
p.setPen(selected ? _st.itemFgOver : (enabled ? _st.itemFg : _st.itemFgDisabled));
p.drawTextLeft(_st.itemPadding.left(), _st.itemPadding.top(), width(), data.text);

View file

@ -31,7 +31,7 @@ public:
Menu(QWidget *parent, const style::Menu &st = st::defaultMenu);
Menu(QWidget *parent, QMenu *menu, const style::Menu &st = st::defaultMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
void clearActions();
@ -92,7 +92,7 @@ private:
// Returns the new width.
int processAction(QAction *action, int index, int width);
QAction *addAction(QAction *a, const style::icon *icon = nullptr);
QAction *addAction(QAction *a, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
void setSelected(int selected);
void clearMouseSelection();
@ -115,6 +115,7 @@ private:
QString text;
QString shortcut;
const style::icon *icon = nullptr;
const style::icon *iconOver = nullptr;
};
using ActionsData = QList<ActionData>;

View file

@ -80,8 +80,8 @@ void PopupMenu::handleMenuResize() {
_inner = QRect(_padding.left(), _padding.top(), width() - _padding.left() - _padding.right(), height() - _padding.top() - _padding.bottom());
}
QAction *PopupMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon) {
return _menu->addAction(text, receiver, member, icon);
QAction *PopupMenu::addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon, const style::icon *iconOver) {
return _menu->addAction(text, receiver, member, icon, iconOver);
}
QAction *PopupMenu::addSeparator() {

View file

@ -28,7 +28,7 @@ public:
PopupMenu(const style::PopupMenu &st = st::defaultPopupMenu);
PopupMenu(QMenu *menu, const style::PopupMenu &st = st::defaultPopupMenu);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr);
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator();
void clearActions();

View file

@ -31,12 +31,11 @@ IconButton {
width: pixels;
height: pixels;
opacity: double;
overOpacity: double;
icon: icon;
iconOver: icon;
iconPosition: point;
downIconPosition: point;
iconPositionDown: point;
duration: int;
}
@ -52,7 +51,7 @@ MaskButton {
iconBgOver: color;
iconPosition: point;
downIconPosition: point;
iconPositionDown: point;
duration: int;
}
@ -61,10 +60,10 @@ MediaSlider {
width: pixels;
activeFg: color;
inactiveFg: color;
disabledActiveFg: color;
disabledInactiveFg: color;
activeOpacity: double;
inactiveOpacity: double;
activeFgOver: color;
inactiveFgOver: color;
activeFgDisabled: color;
inactiveFgDisabled: color;
seekSize: size;
duration: int;
}
@ -137,8 +136,6 @@ Menu {
itemFgShortcutDisabled: color;
itemPadding: margins;
itemIconPosition: point;
itemIconOpacity: double;
itemIconOverOpacity: double;
itemFont: font;
separatorPadding: margins;
@ -184,15 +181,9 @@ defaultLabelSimple: LabelSimple {
textFg: windowTextFg;
}
defaultIconButton: IconButton {
opacity: 0.78;
overOpacity: 1.;
duration: 150;
}
defaultMaskButton: MaskButton {
iconPosition: point(-1px, -1px);
downIconPosition: point(-1px, -1px);
iconPositionDown: point(-1px, -1px);
duration: 150;
}
@ -223,8 +214,6 @@ defaultMenu: Menu {
itemFgShortcutOver: #7c99b2;
itemFgShortcutDisabled: #cccccc;
itemIconPosition: point(0px, 0px);
itemIconOpacity: 1.;
itemIconOverOpacity: 1.;
itemPadding: margins(17px, 8px, 17px, 7px);
itemFont: normalFont;

View file

@ -25,7 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class PeerAvatarButton;
class RoundButton;
class IconButton;
class MaskButton;
} // namespace Ui
namespace Window {
@ -87,7 +87,7 @@ private:
ChildWidget<Ui::PeerAvatarButton> _info;
ChildWidget<Ui::RoundButton> _mediaType;
ChildWidget<Ui::IconButton> _search;
ChildWidget<Ui::MaskButton> _search;
ChildWidget<TWidget> _membersShowArea = { nullptr };
};

View file

@ -36,13 +36,15 @@ notifyPhotoSize: 62px;
notifyMacPhotoSize: 64px;
notifyPhotoPos: point(9px, 9px);
notifyClosePos: point(1px, 2px);
notifyClose: IconButton(defaultIconButton) {
notifyClose: IconButton {
width: 30px;
height: 30px;
icon: simpleCloseIcon;
iconOver: simpleCloseIconOver;
iconPosition: point(10px, 10px);
downIconPosition: point(10px, 11px);
iconPositionDown: point(10px, 11px);
}
notifyItemTop: 12px;
notifyTextLeft: 12px;
@ -68,11 +70,11 @@ notifyReplyArea: InputArea(defaultInputArea) {
borderActive: 0px;
borderError: 0px;
}
notifySendReply: IconButton(defaultIconButton) {
notifySendReply: IconButton {
width: 36px;
height: 36px;
icon: icon {{ "notification_send", windowActiveFill, point(3px, 9px) }};
iconPosition: point(0px, 0px);
downIconPosition: point(0px, 1px);
iconPositionDown: point(0px, 1px);
}