mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/graph] Put parameter name in interval controller
For instance: X Start ... X End ... Step
This commit is contained in:
@@ -36,6 +36,7 @@ bool IntervalParameterSelectorController::handleEvent(Ion::Events::Event event)
|
||||
Shared::IntervalParameterController * controller = App::app()->valuesController()->intervalParameterController();
|
||||
Shared::CartesianFunction::PlotType plotType = plotTypeAtRow(selectedRow());
|
||||
controller->setTitle(messageForType(plotType));
|
||||
setStartEndMessages(controller, plotType);
|
||||
controller->setInterval(App::app()->intervalForType(plotType));
|
||||
stack->push(controller);
|
||||
return true;
|
||||
@@ -97,4 +98,15 @@ I18n::Message IntervalParameterSelectorController::messageForType(Shared::Cartes
|
||||
return message[static_cast<size_t>(plotType)];
|
||||
}
|
||||
|
||||
void IntervalParameterSelectorController::setStartEndMessages(Shared::IntervalParameterController * controller, Shared::CartesianFunction::PlotType plotType) {
|
||||
if (plotType == Shared::CartesianFunction::PlotType::Cartesian) {
|
||||
controller->setStartEndMessages(I18n::Message::XStart, I18n::Message::XEnd);
|
||||
} else if (plotType == Shared::CartesianFunction::PlotType::Polar) {
|
||||
controller->setStartEndMessages(I18n::Message::ThetaStart, I18n::Message::ThetaEnd);
|
||||
} else {
|
||||
assert(plotType == Shared::CartesianFunction::PlotType::Parametric);
|
||||
controller->setStartEndMessages(I18n::Message::TStart, I18n::Message::TEnd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <escher.h>
|
||||
#include "../../shared/cartesian_function.h"
|
||||
#include <apps/shared/interval_parameter_controller.h>
|
||||
|
||||
namespace Graph {
|
||||
|
||||
@@ -19,6 +20,7 @@ public:
|
||||
int reusableCellCount() override;
|
||||
HighlightCell * reusableCell(int index) override;
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
void setStartEndMessages(Shared::IntervalParameterController * controller, Shared::CartesianFunction::PlotType plotType);
|
||||
private:
|
||||
Shared::CartesianFunction::PlotType plotTypeAtRow(int j) const;
|
||||
I18n::Message messageForType(Shared::CartesianFunction::PlotType plotType);
|
||||
|
||||
@@ -20,12 +20,16 @@ ValuesController::ValuesController(Responder * parentResponder, InputEventHandle
|
||||
m_setIntervalButton(this, I18n::Message::IntervalSet, Invocation([](void * context, void * sender) {
|
||||
ValuesController * valuesController = (ValuesController *) context;
|
||||
StackViewController * stack = ((StackViewController *)valuesController->stackController());
|
||||
if (valuesController->intervalParameterSelectorController()->numberOfRows() == 1) {
|
||||
valuesController->intervalParameterController()->setInterval(valuesController->intervalAtColumn(0));
|
||||
stack->push(valuesController->intervalParameterController());
|
||||
IntervalParameterSelectorController * intervalSelectorController = valuesController->intervalParameterSelectorController();
|
||||
if (intervalSelectorController->numberOfRows() == 1) {
|
||||
IntervalParameterController * intervalController = valuesController->intervalParameterController();
|
||||
intervalController->setInterval(valuesController->intervalAtColumn(0));
|
||||
int i = 1;
|
||||
intervalSelectorController->setStartEndMessages(intervalController, valuesController->plotTypeAtColumn(&i));
|
||||
stack->push(intervalController);
|
||||
return true;
|
||||
}
|
||||
stack->push(valuesController->intervalParameterSelectorController());
|
||||
stack->push(intervalSelectorController);
|
||||
return true;
|
||||
}, this), k_font)
|
||||
{
|
||||
@@ -99,7 +103,6 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in
|
||||
myFunctionCell->setColor(function->color());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int ValuesController::typeAtLocation(int i, int j) {
|
||||
@@ -222,6 +225,11 @@ double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int colum
|
||||
return eval.x1();
|
||||
}
|
||||
|
||||
void ValuesController::setStartEndMessages(Shared::IntervalParameterController * controller, int column) {
|
||||
int c = column+1;
|
||||
m_intervalParameterSelectorController.setStartEndMessages(controller, plotTypeAtColumn(&c));
|
||||
}
|
||||
|
||||
void ValuesController::updateNumberOfColumns() {
|
||||
for (int plotTypeIndex = 0; plotTypeIndex < CartesianFunction::k_numberOfPlotTypes; plotTypeIndex++) {
|
||||
m_numberOfColumnsForType[plotTypeIndex] = 0;
|
||||
|
||||
@@ -35,6 +35,7 @@ private:
|
||||
constexpr static int k_maxNumberOfAbscissaCells = Shared::CartesianFunction::k_numberOfPlotTypes * k_maxNumberOfRows;
|
||||
constexpr static int k_maxNumberOfCells = k_maxNumberOfFunctions * k_maxNumberOfRows;
|
||||
|
||||
void setStartEndMessages(Shared::IntervalParameterController * controller, int column) override;
|
||||
void updateNumberOfColumns() override;
|
||||
Ion::Storage::Record recordAtColumn(int i) override;
|
||||
Ion::Storage::Record recordAtColumn(int i, bool * isDerivative);
|
||||
|
||||
@@ -12,6 +12,8 @@ SequenceColor = "Farbe der Folge"
|
||||
DeleteSequence = "Folge löschen"
|
||||
NoSequence = "Keine Folge"
|
||||
NoActivatedSequence = "Keine aktive Folge"
|
||||
NStart = "Startwert"
|
||||
NEnd = "Endwert"
|
||||
TermSum = "Summe der Terme"
|
||||
SelectFirstTerm = "Erster Term "
|
||||
SelectLastTerm = "Letzter Term "
|
||||
|
||||
@@ -12,6 +12,8 @@ SequenceColor = "Sequence color"
|
||||
DeleteSequence = "Delete sequence"
|
||||
NoSequence = "No sequence"
|
||||
NoActivatedSequence = "No sequence is turned on"
|
||||
NStart = "N start"
|
||||
NEnd = "N end"
|
||||
TermSum = "Sum of terms"
|
||||
SelectFirstTerm = "Select First Term "
|
||||
SelectLastTerm = "Select last term "
|
||||
|
||||
@@ -12,6 +12,8 @@ SequenceColor = "Color de la sucesión"
|
||||
DeleteSequence = "Eliminar la sucesión"
|
||||
NoSequence = "Ninguna sucesión"
|
||||
NoActivatedSequence = "Ninguna sucesión activada"
|
||||
NStart = "N inicio"
|
||||
NEnd = "N fin"
|
||||
TermSum = "Suma de términos"
|
||||
SelectFirstTerm = "Seleccionar el primer término "
|
||||
SelectLastTerm = "Seleccionar el último término "
|
||||
|
||||
@@ -12,6 +12,8 @@ SequenceColor = "Couleur de la suite"
|
||||
DeleteSequence = "Supprimer la suite"
|
||||
NoSequence = "Aucune suite"
|
||||
NoActivatedSequence = "Aucune suite activée"
|
||||
NStart = "N début"
|
||||
NEnd = "N fin"
|
||||
TermSum = "Somme des termes"
|
||||
SelectFirstTerm = "Sélectionner le premier terme "
|
||||
SelectLastTerm = "Sélectionner le dernier terme "
|
||||
|
||||
@@ -12,6 +12,8 @@ SequenceColor = "Cor da sequência"
|
||||
DeleteSequence = "Eliminar a sequência"
|
||||
NoSequence = "Sem sequência"
|
||||
NoActivatedSequence = "Sem sequência ativada"
|
||||
NStart = "N início"
|
||||
NEnd = "N fim"
|
||||
TermSum = "Soma dos termos"
|
||||
SelectFirstTerm = "Selecionar primeiro termo "
|
||||
SelectLastTerm = "Selecionar último termo "
|
||||
|
||||
@@ -52,6 +52,10 @@ I18n::Message ValuesController::emptyMessage() {
|
||||
return I18n::Message::NoActivatedSequence;
|
||||
}
|
||||
|
||||
void ValuesController::setStartEndMessages(Shared::IntervalParameterController * controller, int column) {
|
||||
m_intervalParameterController.setStartEndMessages(I18n::Message::NStart, I18n::Message::NEnd);
|
||||
}
|
||||
|
||||
bool ValuesController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) {
|
||||
if (floatBody < 0) {
|
||||
return false;
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
return &m_intervalParameterController;
|
||||
}
|
||||
private:
|
||||
void setStartEndMessages(Shared::IntervalParameterController * controller, int column) override;
|
||||
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
|
||||
Shared::Interval * intervalAtColumn(int columnIndex) override;
|
||||
I18n::Message valuesParameterMessageAtColumn(int columnIndex) const override;
|
||||
|
||||
@@ -14,7 +14,6 @@ Deg = "gra"
|
||||
Deviation = "Varianz"
|
||||
DisplayValues = "Werte anzeigen"
|
||||
Empty = "Leer"
|
||||
End = "Endwert"
|
||||
ExitExamMode1 = "Möchten Sie den Testmodus "
|
||||
ExitExamMode2 = "verlassen?"
|
||||
Exponential = "Exponentielle"
|
||||
@@ -37,10 +36,12 @@ Move = " Verschieben: "
|
||||
NameCannotStartWithNumber = "Ein Name darf nicht mit einer Zahl beginnen"
|
||||
NameTaken = "Dieser Name ist bereits vergeben"
|
||||
NameTooLong = "Der Name ist zu lang"
|
||||
NEnd = "N Endwert"
|
||||
Next = "Nächste"
|
||||
NoDataToPlot = "Keine Daten zum Zeichnen"
|
||||
NoFunctionToDelete = "Keine Funktion zum Löschen"
|
||||
NoValueToCompute = "Keine Größe zum Berechnen"
|
||||
NStart = "N Startwert"
|
||||
Ok = "Bestätigen"
|
||||
Or = " oder "
|
||||
Orthonormal = "Orthonormal"
|
||||
@@ -54,16 +55,21 @@ Sci = "sci/"
|
||||
SquareSum = "Quadratsumme"
|
||||
StatTab = "Stats"
|
||||
StandardDeviation = "Standardabweichung"
|
||||
Start = "Startwert"
|
||||
Step = "Schrittwert"
|
||||
StorageMemoryFull1 = "Der Speicher ist voll. Löschen Sie"
|
||||
StorageMemoryFull2 = "von Daten und versuchen Sie es erneut."
|
||||
StoreExpressionNotAllowed = "'store' ist verboten"
|
||||
SyntaxError = "Syntaxfehler"
|
||||
TEnd = "T Endwert"
|
||||
ThetaEnd = "θ Endwert"
|
||||
ThetaStart = "θ Startwert"
|
||||
TStart = "T Startwert"
|
||||
ToZoom = "Zoom: "
|
||||
Trigonometric = "Trigonometrisch"
|
||||
UndefinedValue = "Nicht definierter Wert"
|
||||
ValueNotReachedByFunction = "Der Wert wird von der Funktion nicht erreicht"
|
||||
ValuesTab = "Tabelle"
|
||||
Warning = "Achtung"
|
||||
XEnd = "X Endwert"
|
||||
XStart = "X Startwert"
|
||||
Zoom = "Zoom"
|
||||
|
||||
@@ -14,7 +14,6 @@ Deg = "deg"
|
||||
Deviation = "Variance"
|
||||
DisplayValues = "Display values"
|
||||
Empty = "Empty"
|
||||
End = "End"
|
||||
ExitExamMode1 = "Exit the exam "
|
||||
ExitExamMode2 = "mode?"
|
||||
Exponential = "Exponential"
|
||||
@@ -41,6 +40,8 @@ Next = "Next"
|
||||
NoDataToPlot = "No data to draw"
|
||||
NoFunctionToDelete = "No function to delete"
|
||||
NoValueToCompute = "No values to calculate"
|
||||
NEnd = "N end"
|
||||
NStart = "N start"
|
||||
Ok = "Confirm"
|
||||
Or = " or "
|
||||
Orthonormal = "Orthonormal"
|
||||
@@ -54,16 +55,21 @@ Sci = "sci/"
|
||||
SquareSum = "Sum of squares"
|
||||
StandardDeviation = "Standard deviation"
|
||||
StoreExpressionNotAllowed = "'store' is not allowed"
|
||||
Start = "Start"
|
||||
StatTab = "Stats"
|
||||
Step = "Step"
|
||||
StorageMemoryFull1 = "The memory is full."
|
||||
StorageMemoryFull2 = "Erase data and try again."
|
||||
SyntaxError = "Syntax error"
|
||||
TEnd = "T end"
|
||||
ThetaEnd = "θ end"
|
||||
ThetaStart = "θ start"
|
||||
TStart = "T start"
|
||||
ToZoom = "Zoom: "
|
||||
Trigonometric = "Trigonometrical"
|
||||
UndefinedValue = "Undefined value"
|
||||
ValueNotReachedByFunction = "Value not reached by function"
|
||||
ValuesTab = "Table"
|
||||
Warning = "Warning"
|
||||
XEnd = "X end"
|
||||
XStart = "X start"
|
||||
Zoom = "Zoom"
|
||||
|
||||
@@ -14,7 +14,6 @@ Deg = "gra"
|
||||
Deviation = "Varianza"
|
||||
DisplayValues = "Visualizar los valores"
|
||||
Empty = "Vacio"
|
||||
End = "Fin"
|
||||
ExitExamMode1 = "Salir del modo "
|
||||
ExitExamMode2 = "examen ?"
|
||||
Exponential = "Exponencial"
|
||||
@@ -37,10 +36,12 @@ Move = " Mover : "
|
||||
NameCannotStartWithNumber = "Un nombre no puede empezar con un número"
|
||||
NameTaken = "Este nombre ya está en uso"
|
||||
NameTooLong = "Este nombre es demasiado largo"
|
||||
NEnd = "N fin"
|
||||
Next = "Siguiente"
|
||||
NoDataToPlot = "Ningunos datos que dibujar"
|
||||
NoFunctionToDelete = "Ninguna función que eliminar"
|
||||
NoValueToCompute = "Ninguna medida que calcular"
|
||||
NStart = "N inicio"
|
||||
Ok = "Confirmar"
|
||||
Or = " o "
|
||||
Orthonormal = "Ortonormal"
|
||||
@@ -53,17 +54,22 @@ RoundAbscissa = "Abscisas enteras"
|
||||
Sci = "sci/"
|
||||
SquareSum = "Suma cuadrados"
|
||||
StandardDeviation = "Desviación típica"
|
||||
Start = "Inicio"
|
||||
StatTab = "Medidas"
|
||||
Step = "Incremento"
|
||||
StorageMemoryFull1 = "La memoria está llena."
|
||||
StorageMemoryFull2 = "Borre datos e intente de nuevo."
|
||||
StoreExpressionNotAllowed = "'store' no está permitido"
|
||||
SyntaxError = "Error sintáctico"
|
||||
TEnd = "T fin"
|
||||
ThetaEnd = "θ fin"
|
||||
ThetaStart = "θ inicio"
|
||||
TStart = "T inicio"
|
||||
ToZoom = "Zoom : "
|
||||
Trigonometric = "Trigonométrico"
|
||||
UndefinedValue = "Valor indefinido"
|
||||
ValueNotReachedByFunction = "No se alcanza este valor"
|
||||
ValuesTab = "Tabla"
|
||||
Warning = "Cuidado"
|
||||
XEnd = "X fin"
|
||||
XStart = "X inicio"
|
||||
Zoom = "Zoom"
|
||||
|
||||
@@ -14,7 +14,6 @@ Deg = "deg"
|
||||
Deviation = "Variance"
|
||||
DisplayValues = "Afficher les valeurs"
|
||||
Empty = "Vide"
|
||||
End = "Fin"
|
||||
ExitExamMode1 = "Voulez-vous sortir "
|
||||
ExitExamMode2 = "du mode examen ?"
|
||||
Exponential = "Exponentielle"
|
||||
@@ -38,9 +37,11 @@ NameCannotStartWithNumber = "Un nom ne peut pas commencer par un chiffre"
|
||||
NameTaken = "Ce nom est déjà utilisé"
|
||||
NameTooLong = "Ce nom est trop long"
|
||||
Next = "Suivant"
|
||||
NEnd = "N fin"
|
||||
NoDataToPlot = "Aucune donnée à tracer"
|
||||
NoFunctionToDelete = "Pas de fonction à supprimer"
|
||||
NoValueToCompute = "Aucune grandeur à calculer"
|
||||
NStart = "N début"
|
||||
Ok = "Valider"
|
||||
Or = " ou "
|
||||
Orthonormal = "Orthonormé"
|
||||
@@ -53,17 +54,22 @@ RoundAbscissa = "Abscisses entières"
|
||||
Sci = "sci/"
|
||||
SquareSum = "Somme des carrés"
|
||||
StandardDeviation = "Écart type"
|
||||
Start = "Début"
|
||||
StatTab = "Stats"
|
||||
Step = "Pas"
|
||||
StorageMemoryFull1 = "La mémoire est pleine."
|
||||
StorageMemoryFull2 = "Effacez des données et réessayez."
|
||||
StoreExpressionNotAllowed = "'store' n'est pas autorisé"
|
||||
SyntaxError = "Attention à la syntaxe"
|
||||
TEnd = "T fin"
|
||||
ThetaEnd = "θ fin"
|
||||
ThetaStart = "θ début"
|
||||
TStart = "T début"
|
||||
ToZoom = "Zoomer : "
|
||||
Trigonometric = "Trigonométrique"
|
||||
UndefinedValue = "Valeur non définie"
|
||||
ValueNotReachedByFunction = "Valeur non atteinte par la fonction"
|
||||
ValuesTab = "Tableau"
|
||||
Warning = "Attention"
|
||||
XEnd = "X fin"
|
||||
XStart = "X début"
|
||||
Zoom = "Zoom"
|
||||
|
||||
@@ -14,7 +14,6 @@ Deg = "gra"
|
||||
Deviation = "Variancia"
|
||||
DisplayValues = "Exibir os valores"
|
||||
Empty = "Vácuo"
|
||||
End = "Fim"
|
||||
ExitExamMode1 = "Você quer sair do modo de "
|
||||
ExitExamMode2 = "exame ?"
|
||||
Exponential = "Exponencial"
|
||||
@@ -37,10 +36,12 @@ Move = " Mover : "
|
||||
NameCannotStartWithNumber = "Um nome não pode começar com um número"
|
||||
NameTaken = "Este nome é já usado"
|
||||
NameTooLong = "Este nome é muito longo"
|
||||
NEnd = "N fim"
|
||||
Next = "Seguinte"
|
||||
NoDataToPlot = "Não ha dados para desenhar"
|
||||
NoFunctionToDelete = "Sem função para eliminar"
|
||||
NoValueToCompute = "Nenhuma quantidade para calcular"
|
||||
NStart = "N inicio"
|
||||
Ok = "Confirmar"
|
||||
Or = " ou "
|
||||
Orthonormal = "Ortonormado"
|
||||
@@ -53,17 +54,22 @@ RoundAbscissa = "Inteiro"
|
||||
Sci = "sci/"
|
||||
SquareSum = "Soma dos quadrados"
|
||||
StandardDeviation = "Desvio padrão"
|
||||
Start = "Inicio"
|
||||
StatTab = "Estat"
|
||||
Step = "Passo"
|
||||
StorageMemoryFull1 = "A memoria esta chéia."
|
||||
StorageMemoryFull2 = "Apage dados e tente novamente."
|
||||
StoreExpressionNotAllowed = "'store' não está permitido"
|
||||
SyntaxError = "Erro de sintaxe"
|
||||
TEnd = "T fim"
|
||||
ThetaEnd = "θ fim"
|
||||
ThetaStart = "θ inicio"
|
||||
TStart = "T inicio"
|
||||
ToZoom = "Zoom : "
|
||||
Trigonometric = "Trigonométrico"
|
||||
UndefinedValue = "Valor indefinido"
|
||||
ValueNotReachedByFunction = "O valor não é alcançado pela função"
|
||||
ValuesTab = "Tabela"
|
||||
Warning = "Atenção"
|
||||
XEnd = "X fim"
|
||||
XStart = "X inicio"
|
||||
Zoom = "Zoom"
|
||||
|
||||
@@ -6,7 +6,9 @@ IntervalParameterController::IntervalParameterController(Responder * parentRespo
|
||||
FloatParameterController<double>(parentResponder),
|
||||
m_interval(nullptr),
|
||||
m_intervalCells{},
|
||||
m_title(I18n::Message::IntervalSet)
|
||||
m_title(I18n::Message::IntervalSet),
|
||||
m_startMessage(I18n::Message::XStart),
|
||||
m_endMessage(I18n::Message::XEnd)
|
||||
{
|
||||
for (int i = 0; i < k_totalNumberOfCell; i++) {
|
||||
m_intervalCells[i].setParentResponder(&m_selectableTableView);
|
||||
@@ -22,13 +24,20 @@ int IntervalParameterController::numberOfRows() {
|
||||
return k_totalNumberOfCell+1;
|
||||
}
|
||||
|
||||
void IntervalParameterController::setStartEndMessages(I18n::Message startMessage, I18n::Message endMessage) {
|
||||
m_startMessage = startMessage;
|
||||
m_endMessage = endMessage;
|
||||
}
|
||||
|
||||
void IntervalParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if (index == numberOfRows()-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)cell;
|
||||
I18n::Message labels[k_totalNumberOfCell] = {I18n::Message::Start, I18n::Message::End, I18n::Message::Step};
|
||||
myCell->setMessage(labels[index]);
|
||||
assert(index >= 0 && index < 3);
|
||||
I18n::Message m = index == 0 ? m_startMessage : (index == 1 ? m_endMessage : I18n::Message::Step);
|
||||
myCell->setMessage(m);
|
||||
FloatParameterController::willDisplayCellForIndex(cell, index);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
void setTitle(I18n::Message title) { m_title = title; }
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
int numberOfRows() override;
|
||||
void setStartEndMessages(I18n::Message startMessage, I18n::Message endMessage);
|
||||
protected:
|
||||
constexpr static int k_totalNumberOfCell = 3;
|
||||
bool setParameterAtIndex(int parameterIndex, double f) override;
|
||||
@@ -29,6 +30,8 @@ private:
|
||||
void buttonAction() override;
|
||||
MessageTableCellWithEditableText m_intervalCells[k_totalNumberOfCell];
|
||||
I18n::Message m_title;
|
||||
I18n::Message m_startMessage;
|
||||
I18n::Message m_endMessage;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
if (typeAtLocation(selectedColumn(), 0) == k_abscissaTitleCellType) {
|
||||
m_abscissaParameterController.setPageTitle(valuesParameterMessageAtColumn(selectedColumn()));
|
||||
intervalParameterController()->setInterval(intervalAtColumn(selectedColumn()));
|
||||
setStartEndMessages(intervalParameterController(), selectedColumn());
|
||||
parameterController = &m_abscissaParameterController;
|
||||
} else {
|
||||
parameterController = functionParameterController();
|
||||
|
||||
@@ -57,6 +57,7 @@ protected:
|
||||
bool m_numberOfColumnsNeedUpdate;
|
||||
SelectableTableView m_selectableTableView;
|
||||
private:
|
||||
virtual void setStartEndMessages(Shared::IntervalParameterController * controller, int column) = 0;
|
||||
Responder * tabController() const override;
|
||||
bool cellAtLocationIsEditable(int columnIndex, int rowIndex) override;
|
||||
double dataAtLocation(int columnIndex, int rowIndex) override;
|
||||
|
||||
Reference in New Issue
Block a user