Blame view

build3/apps/shared/text_field_delegate_app.cpp 3.67 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  #include "text_field_delegate_app.h"
  #include "../apps_container.h"
  #include <cmath>
  #include <string.h>
  
  using namespace Poincare;
  
  namespace Shared {
  
  TextFieldDelegateApp::TextFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) :
    ::App(container, snapshot, rootViewController, I18n::Message::Warning),
    TextFieldDelegate()
  {
  }
  
  Context * TextFieldDelegateApp::localContext() {
    return container()->globalContext();
  }
  
  AppsContainer * TextFieldDelegateApp::container() {
    return (AppsContainer *)app()->container();
  }
  
  const char * TextFieldDelegateApp::XNT() {
    return "X";
  }
  
  const char * TextFieldDelegateApp::privateXNT(TextField * textField) {
    static constexpr struct { const char *name, *xnt; } sFunctions[] = {
      { "diff", "x" }, { "int", "x" },
      { "product", "n" }, { "sum", "n" }
    };
    // Let's assume everything before the cursor is nested correctly, which is reasonable if the expression is being entered left-to-right.
    const char * text = textField->text();
    size_t location = textField->cursorLocation();
    unsigned level = 0;
    while (location >= 1) {
      location--;
      switch (text[location]) {
        case '(':
          // Check if we are skipping to the next matching '('.
          if (level) {
            level--;
            break;
          }
          // Skip over whitespace.
          while (location >= 1 && text[location-1] == ' ') {
            location--;
          }
          // We found the next innermost function we are currently in.
          for (size_t i = 0; i < sizeof(sFunctions)/sizeof(sFunctions[0]); i++) {
            const char * name = sFunctions[i].name;
            size_t length = strlen(name);
            if (location >= length && memcmp(&text[location-length], name, length) == 0) {
              return sFunctions[i].xnt;
            }
          }
          break;
        case ',':
          // Commas encountered while skipping to the next matching '(' should be ignored.
          if (level) {
            break;
          }
          // FALLTHROUGH
        case ')':
          // Skip to the next matching '('.
          level++;
          break;
      }
    }
    // Fallback to the default
    return XNT();
  }
  
  bool TextFieldDelegateApp::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
    return event == Ion::Events::OK || event == Ion::Events::EXE;
  }
  
  bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
    if (textField->isEditing() && textField->textFieldShouldFinishEditing(event)) {
      Expression * exp = Expression::parse(textField->text());
      if (exp != nullptr) {
        delete exp;
      }
      if (exp == nullptr) {
        textField->app()->displayWarning(I18n::Message::SyntaxError);
        return true;
      }
    }
    if (event == Ion::Events::Var) {
      if (!textField->isEditing()) {
        textField->setEditing(true);
      }
      AppsContainer * appsContainer = (AppsContainer *)textField->app()->container();
      VariableBoxController * variableBoxController = appsContainer->variableBoxController();
      variableBoxController->setTextFieldCaller(textField);
      textField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
      return true;
    }
    if (event == Ion::Events::XNT) {
      if (!textField->isEditing()) {
        textField->setEditing(true);
      }
      const char * xnt = privateXNT(textField);
      textField->insertTextAtLocation(xnt, textField->cursorLocation());
      textField->setCursorLocation(textField->cursorLocation()+strlen(xnt));
      return true;
    }
    return false;
  }
  
  Toolbox * TextFieldDelegateApp::toolboxForTextField(TextField * textField) {
    return container()->mathToolbox();
  }
  
  }