Make IV editor table toolbar button context-aware

This commit is contained in:
John Preston
2026-06-24 21:29:39 +04:00
parent c89afaaa19
commit a36e7e6741
3 changed files with 91 additions and 5 deletions
@@ -207,6 +207,8 @@ private:
void showTextStyleMenu(not_null<Ui::IconButton*> button);
void fillListStyleMenu(not_null<Ui::PopupMenu*> menu);
void showListStyleMenu(not_null<Ui::IconButton*> button);
void fillTableStyleMenu(not_null<Ui::PopupMenu*> menu);
void showTableStyleMenu(not_null<Ui::IconButton*> button);
void applyBlockText();
void updateFromEditorState();
@@ -223,6 +225,7 @@ private:
Ui::IconButton *_linkButton = nullptr;
Ui::IconButton *_emojiButton = nullptr;
Ui::IconButton *_listButton = nullptr;
Ui::IconButton *_tableButton = nullptr;
base::unique_qptr<Ui::PopupMenu> _menu;
};
@@ -534,11 +537,20 @@ void Toolbar::buildPills() {
showListStyleMenu(listStyle);
});
_listButton = listStyle;
addPillButton(
const auto tableStyle = addPillButton(
controls,
ToolbarActionId::Table,
&st::ivEditorToolbarTableIcon,
[=] { insertType(State::InsertBlockType::Table); });
nullptr);
tableStyle->setIsMenuButton(true);
tableStyle->setClickedCallback([=] {
if (_editor && _editor->currentTableRangeAtCaret()) {
showTableStyleMenu(tableStyle);
} else {
insertType(State::InsertBlockType::Table);
}
});
_tableButton = tableStyle;
_linkButton = addPillButton(
controls,
ToolbarActionId::Link,
@@ -838,6 +850,32 @@ void Toolbar::showListStyleMenu(not_null<Ui::IconButton*> button) {
_menu->popup(button->mapToGlobal(QPoint(0, button->height())));
}
void Toolbar::fillTableStyleMenu(not_null<Ui::PopupMenu*> menu) {
if (!_editor) {
return;
}
const auto range = _editor->currentTableRangeAtCaret();
if (!range) {
return;
}
_editor->fillTableChangeMenu(menu, *range);
}
void Toolbar::showTableStyleMenu(not_null<Ui::IconButton*> button) {
if (_menu) {
return;
}
auto menu = base::make_unique_q<Ui::PopupMenu>(
this,
st::popupMenuWithIcons);
fillTableStyleMenu(not_null<Ui::PopupMenu*>(menu.get()));
if (menu->empty()) {
return;
}
_menu = std::move(menu);
_menu->popup(button->mapToGlobal(QPoint(0, button->height())));
}
void Toolbar::updateFromEditorState() {
for (const auto &pb : _stateButtons) {
const auto &state = _toolbarState[pb.format];
@@ -861,6 +899,15 @@ void Toolbar::updateFromEditorState() {
? ToolbarButtonState::Active
: ToolbarButtonState::Inactive);
}
if (_tableButton) {
const auto inTable = _editor
&& _editor->currentTableRangeAtCaret().has_value();
SetupToolbarButton(
not_null<Ui::IconButton*>(_tableButton),
inTable
? ToolbarButtonState::Active
: ToolbarButtonState::Inactive);
}
}
void Toolbar::setEmojiColumnOpen(bool open) {
@@ -4588,6 +4588,43 @@ State::ListSelectionInfo Widget::listSelectionInfo(
return _state->listSelectionInfo(range);
}
std::optional<PreparedEditTableCellRange>
Widget::currentTableRangeAtCaret() const {
const auto activeLeaf = _state->activePreparedLeafSource();
if (!activeLeaf
|| activeLeaf->kind != PreparedEditLeafKind::TableCellText
|| activeLeaf->tableRowIndex < 0
|| activeLeaf->tableCellIndex < 0) {
return std::nullopt;
}
const auto path = _state->convertBlockPath(activeLeaf->block);
const auto block = path
? BlockFromPath(_state->richPage(), *path)
: nullptr;
if (!block || block->kind != RichPage::BlockKind::Table) {
return std::nullopt;
}
const auto grid = BuildTableGrid(*block);
for (const auto &cell : grid.cells) {
if (cell.rowIndex != activeLeaf->tableRowIndex
|| cell.cellIndex != activeLeaf->tableCellIndex) {
continue;
}
auto range = PreparedEditTableCellRange{
.block = activeLeaf->block,
.rowFrom = cell.rowFrom,
.rowTill = cell.rowTill,
.columnFrom = cell.columnFrom,
.columnTill = cell.columnTill,
};
if (range.empty() || !_state->tableSelectionInfo(range).valid) {
return std::nullopt;
}
return range;
}
return std::nullopt;
}
void Widget::showListContextMenu(
const PreparedListItemRange &range,
QPoint globalPos) {
@@ -177,6 +177,8 @@ public:
[[nodiscard]] ActiveBlockInfo activeBlockInfo() const;
[[nodiscard]] std::optional<Markdown::PreparedEditListItemRange>
currentListRangeAtCaret() const;
[[nodiscard]] std::optional<Markdown::PreparedEditTableCellRange>
currentTableRangeAtCaret() const;
[[nodiscard]] std::optional<Markdown::PreparedEditListItemRange>
currentListItemRangeAtCaret();
[[nodiscard]] State::ListSelectionInfo listSelectionInfo(
@@ -187,6 +189,9 @@ public:
void fillListItemChangeMenu(
not_null<Ui::PopupMenu*> menu,
const Markdown::PreparedEditListItemRange &range);
void fillTableChangeMenu(
not_null<Ui::PopupMenu*> menu,
const Markdown::PreparedEditTableCellRange &range);
void setInlineFieldExternalInteractionActive(bool active);
void setTopContentPadding(int value);
@@ -668,9 +673,6 @@ private:
void showTableContextMenu(
const Markdown::PreparedEditTableCellRange &range,
QPoint globalPos);
void fillTableChangeMenu(
not_null<Ui::PopupMenu*> menu,
const Markdown::PreparedEditTableCellRange &range);
void applyTableChange(Fn<bool()> change);
[[nodiscard]] std::optional<State::BlockPath> simpleMediaBlockPathFromHit(
const Markdown::PreparedEditHit &hit) const;