[code] Navigation in the console history.

The user can copy previous commands or results, into the clipboard or in
the console prompt.

Change-Id: I280fff2d4937f4d17ab6c8907d6e5c359a322372
This commit is contained in:
Léa Saviot
2017-10-25 17:11:41 +02:00
committed by Romain Goyet
parent 745eddfa05
commit 239e702d37
8 changed files with 66 additions and 18 deletions

View File

@@ -34,16 +34,16 @@ void HistoryViewCell::layoutSubviews() {
KDCoordinate width = bounds().width();
KDCoordinate height = bounds().height();
KDSize inputSize = m_inputView.minimalSizeForOptimalDisplay();
if (inputSize.width() + k_digitHorizontalMargin > width) {
m_inputView.setFrame(KDRect(k_digitHorizontalMargin, k_digitVerticalMargin, width - k_digitHorizontalMargin, inputSize.height()));
if (inputSize.width() + Metric::HistoryHorizontalMargin > width) {
m_inputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, inputSize.height()));
} else {
m_inputView.setFrame(KDRect(k_digitHorizontalMargin, k_digitVerticalMargin, inputSize.width(), inputSize.height()));
m_inputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, k_digitVerticalMargin, inputSize.width(), inputSize.height()));
}
KDSize outputSize = m_outputView.minimalSizeForOptimalDisplay();
if (outputSize.width() + k_digitHorizontalMargin > width) {
m_outputView.setFrame(KDRect(k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - k_digitHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin));
if (outputSize.width() + Metric::HistoryHorizontalMargin > width) {
m_outputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin));
} else {
m_outputView.setFrame(KDRect(width - outputSize.width() - k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin));
m_outputView.setFrame(KDRect(width - outputSize.width() - Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin));
}
}

View File

@@ -22,7 +22,6 @@ public:
void layoutSubviews() override;
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
constexpr static KDCoordinate k_digitHorizontalMargin = 10;
constexpr static KDCoordinate k_digitVerticalMargin = 5;
SubviewType selectedSubviewType();
void setSelectedSubviewType(HistoryViewCell::SubviewType subviewType);

View File

@@ -1,7 +1,7 @@
#include "console_controller.h"
#include "script.h"
#include <apps/i18n.h>
#include "app.h"
#include <apps/i18n.h>
#include <assert.h>
extern "C" {
@@ -12,9 +12,10 @@ namespace Code {
ConsoleController::ConsoleController(Responder * parentResponder, ScriptStore * scriptStore) :
ViewController(parentResponder),
SelectableTableViewDataSource(),
TextFieldDelegate(),
m_rowHeight(KDText::charSize(k_fontSize).height()),
m_tableView(this, this, 0, 0),
m_selectableTableView(this, this, 0, 1, 0, Metric::CommonRightMargin, 3, Metric::HistoryHorizontalMargin, this, this, true, true, KDColorWhite),
m_editCell(this, this),
m_pythonHeap(nullptr),
m_scriptStore(scriptStore)
@@ -67,7 +68,7 @@ void ConsoleController::runAndPrintForCommand(const char * command) {
runCode(command);
flushOutputAccumulationBufferToStore();
m_consoleStore.deleteLastLineIfEmpty();
m_tableView.reloadData();
m_selectableTableView.reloadData();
m_editCell.setEditing(true);
}
@@ -83,8 +84,8 @@ void ConsoleController::removeExtensionIfAny(char * name) {
void ConsoleController::viewWillAppear() {
assert(pythonEnvironmentIsLoaded());
m_tableView.reloadData();
m_tableView.scrollToCell(0, m_consoleStore.numberOfLines());
m_selectableTableView.reloadData();
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
m_editCell.setEditing(true);
}
@@ -92,6 +93,34 @@ void ConsoleController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_editCell);
}
bool ConsoleController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Up) {
if (m_consoleStore.numberOfLines() > 0 && m_selectableTableView.selectedRow() > 0) {
m_editCell.setEditing(false);
m_editCell.setText("");
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines()-1);
app()->setFirstResponder(&m_selectableTableView);
return true;
}
} else if (event == Ion::Events::OK || event == Ion::Events::EXE) {
if (m_consoleStore.numberOfLines() > 0) {
const char * text = m_consoleStore.lineAtIndex(m_selectableTableView.selectedRow()).text();
m_editCell.setEditing(true);
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
app()->setFirstResponder(&m_editCell);
m_editCell.setText(text);
return true;
}
} else if (event == Ion::Events::Copy) {
int row = m_selectableTableView.selectedRow();
if (row < m_consoleStore.numberOfLines()) {
Clipboard::sharedClipboard()->store(m_consoleStore.lineAtIndex(row).text());
return true;
}
}
return false;
}
int ConsoleController::numberOfRows() {
return m_consoleStore.numberOfLines()+1;
}
@@ -146,6 +175,13 @@ void ConsoleController::willDisplayCellAtLocation(HighlightCell * cell, int i, i
}
}
void ConsoleController::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) {
if (t->selectedRow() == m_consoleStore.numberOfLines()) {
m_editCell.setEditing(true);
app()->setFirstResponder(&m_editCell);
}
}
bool ConsoleController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
return event == Ion::Events::OK || event == Ion::Events::EXE;
}
@@ -157,7 +193,7 @@ bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Eve
bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
runAndPrintForCommand(text);
textField->setText("");
m_tableView.scrollToCell(0, m_consoleStore.numberOfLines());
m_selectableTableView.selectCellAtLocation(0, m_consoleStore.numberOfLines());
return true;
}

View File

@@ -11,7 +11,7 @@
namespace Code {
class ConsoleController : public ViewController, public ListViewDataSource, public ScrollViewDataSource, public TextFieldDelegate, public MicroPython::ExecutionEnvironment {
class ConsoleController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate, public TextFieldDelegate, public MicroPython::ExecutionEnvironment {
public:
static constexpr KDText::FontSize k_fontSize = KDText::FontSize::Large;
@@ -31,9 +31,10 @@ public:
void removeExtensionIfAny(char * name);
// ViewController
View * view() override { return &m_tableView; }
View * view() override { return &m_selectableTableView; }
void viewWillAppear() override;
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
// ListViewDataSource
int numberOfRows() override;
@@ -45,6 +46,9 @@ public:
int typeAtLocation(int i, int j) override;
void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override;
// SelectableTableViewDelegate
void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY) override;
// TextFieldDelegate
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
@@ -68,7 +72,7 @@ private:
int firstNewLineCharIndex(const char * text, size_t length);
int m_rowHeight;
ConsoleStore m_consoleStore;
TableView m_tableView;
SelectableTableView m_selectableTableView;
ConsoleLineCell m_cells[k_numberOfLineCells];
ConsoleEditCell m_editCell;
char * m_pythonHeap;

View File

@@ -9,6 +9,8 @@ namespace Code {
ConsoleEditCell::ConsoleEditCell(Responder * parentResponder, TextFieldDelegate * delegate) :
HighlightCell(),
Responder(parentResponder),
m_textBuffer{0},
m_draftTextBuffer{0},
m_promptView(ConsoleController::k_fontSize, I18n::Message::ConsolePrompt, 0, 0.5),
m_textField(this, m_textBuffer, m_draftTextBuffer, TextField::maxBufferSize(), delegate, true, ConsoleController::k_fontSize)
{
@@ -41,4 +43,8 @@ void ConsoleEditCell::setEditing(bool isEditing) {
m_textField.setEditing(isEditing);
}
void ConsoleEditCell::setText(const char * text) {
m_textField.setText(text);
}
}

View File

@@ -23,6 +23,7 @@ public:
// Edit cell
void setEditing(bool isEditing);
void setText(const char * text);
private:
char m_textBuffer[TextField::maxBufferSize()];

View File

@@ -13,13 +13,14 @@ ConsoleLineCell::ConsoleLineCell() :
}
void ConsoleLineCell::drawRect(KDContext * ctx, KDRect rect) const {
KDColor textBackgroundColor = isHighlighted() ? Palette::Select : KDColorWhite;
ctx->fillRect(bounds(), KDColorWhite);
if (m_line.type() == ConsoleLine::Type::Command) {
ctx->drawString(I18n::translate(I18n::Message::ConsolePrompt), KDPointZero, ConsoleController::k_fontSize);
KDCoordinate chevronsWidth = KDText::stringSize(I18n::translate(I18n::Message::ConsolePrompt), ConsoleController::k_fontSize).width();
ctx->drawString(m_line.text(), KDPoint(chevronsWidth, KDCoordinate(0)), ConsoleController::k_fontSize);
ctx->drawString(m_line.text(), KDPoint(chevronsWidth, KDCoordinate(0)), ConsoleController::k_fontSize, KDColorBlack, textBackgroundColor);
} else {
ctx->drawString(m_line.text(), KDPointZero, ConsoleController::k_fontSize);
ctx->drawString(m_line.text(), KDPointZero, ConsoleController::k_fontSize, KDColorBlack, textBackgroundColor);
}
}

View File

@@ -60,6 +60,7 @@ bool ScriptParameterController::handleEvent(Ion::Events::Event event) {
m_autoImport = !m_autoImport;
m_selectableTableView.reloadData();
m_menuController->reloadConsole();
app()->setFirstResponder(&m_selectableTableView);
return true;
case 3:
dismissScriptParameterController();