瀏覽代碼

Spreadsheet: Allow the user to format Identity cells via JS expressions

Also add some hints as to what the format field expects as it would be
very confusing otherwise.
Ali Mohammad Pur 3 年之前
父節點
當前提交
292e459901

+ 7 - 0
Userland/Applications/Spreadsheet/CellType/Date.cpp

@@ -37,4 +37,11 @@ JS::ThrowCompletionOr<JS::Value> DateCell::js_value(Cell& cell, const CellTypeMe
     return JS::Value(value / 1000); // Turn it to seconds
     return JS::Value(value / 1000); // Turn it to seconds
 }
 }
 
 
+String DateCell::metadata_hint(MetadataName metadata) const
+{
+    if (metadata == MetadataName::Format)
+        return "Date format string as supported by `strftime'";
+    return {};
+}
+
 }
 }

+ 1 - 0
Userland/Applications/Spreadsheet/CellType/Date.h

@@ -18,6 +18,7 @@ public:
     virtual ~DateCell() override = default;
     virtual ~DateCell() override = default;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
+    String metadata_hint(MetadataName) const override;
 };
 };
 
 
 }
 }

+ 16 - 2
Userland/Applications/Spreadsheet/CellType/Identity.cpp

@@ -15,9 +15,13 @@ IdentityCell::IdentityCell()
 {
 {
 }
 }
 
 
-JS::ThrowCompletionOr<String> IdentityCell::display(Cell& cell, const CellTypeMetadata&) const
+JS::ThrowCompletionOr<String> IdentityCell::display(Cell& cell, const CellTypeMetadata& metadata) const
 {
 {
-    return cell.js_data().to_string(cell.sheet().global_object());
+    auto data = cell.js_data();
+    if (!metadata.format.is_empty())
+        data = TRY(cell.sheet().evaluate(metadata.format, &cell));
+
+    return data.to_string(cell.sheet().global_object());
 }
 }
 
 
 JS::ThrowCompletionOr<JS::Value> IdentityCell::js_value(Cell& cell, const CellTypeMetadata&) const
 JS::ThrowCompletionOr<JS::Value> IdentityCell::js_value(Cell& cell, const CellTypeMetadata&) const
@@ -25,4 +29,14 @@ JS::ThrowCompletionOr<JS::Value> IdentityCell::js_value(Cell& cell, const CellTy
     return cell.js_data();
     return cell.js_data();
 }
 }
 
 
+String IdentityCell::metadata_hint(MetadataName metadata) const
+{
+    if (metadata == MetadataName::Length)
+        return "Ignored";
+    if (metadata == MetadataName::Format)
+        return "JavaScript expression, `value' refers to the cell's value";
+
+    return {};
+}
+
 }
 }

+ 1 - 0
Userland/Applications/Spreadsheet/CellType/Identity.h

@@ -17,6 +17,7 @@ public:
     virtual ~IdentityCell() override = default;
     virtual ~IdentityCell() override = default;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
+    String metadata_hint(MetadataName) const override;
 };
 };
 
 
 }
 }

+ 8 - 0
Userland/Applications/Spreadsheet/CellType/Numeric.cpp

@@ -41,4 +41,12 @@ JS::ThrowCompletionOr<JS::Value> NumericCell::js_value(Cell& cell, const CellTyp
     });
     });
 }
 }
 
 
+String NumericCell::metadata_hint(MetadataName metadata) const
+{
+    if (metadata == MetadataName::Format)
+        return "Format string as accepted by `printf', all numeric formats refer to the same value (the cell's value)";
+
+    return {};
+}
+
 }
 }

+ 1 - 0
Userland/Applications/Spreadsheet/CellType/Numeric.h

@@ -28,6 +28,7 @@ public:
     virtual ~NumericCell() override = default;
     virtual ~NumericCell() override = default;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
+    String metadata_hint(MetadataName) const override;
 };
 };
 
 
 }
 }

+ 7 - 0
Userland/Applications/Spreadsheet/CellType/String.cpp

@@ -30,4 +30,11 @@ JS::ThrowCompletionOr<JS::Value> StringCell::js_value(Cell& cell, const CellType
     return JS::js_string(cell.sheet().interpreter().heap(), string);
     return JS::js_string(cell.sheet().interpreter().heap(), string);
 }
 }
 
 
+String StringCell::metadata_hint(MetadataName metadata) const
+{
+    if (metadata == MetadataName::Format)
+        return "Ignored";
+    return {};
+}
+
 }
 }

+ 1 - 0
Userland/Applications/Spreadsheet/CellType/String.h

@@ -17,6 +17,7 @@ public:
     virtual ~StringCell() override = default;
     virtual ~StringCell() override = default;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const override;
+    String metadata_hint(MetadataName) const override;
 };
 };
 
 
 }
 }

+ 8 - 0
Userland/Applications/Spreadsheet/CellType/Type.h

@@ -23,6 +23,13 @@ struct CellTypeMetadata {
     Format static_format;
     Format static_format;
 };
 };
 
 
+enum class MetadataName {
+    Length,
+    Format,
+    Alignment,
+    StaticFormat,
+};
+
 class CellType {
 class CellType {
 public:
 public:
     static const CellType* get_by_name(StringView);
     static const CellType* get_by_name(StringView);
@@ -30,6 +37,7 @@ public:
 
 
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const = 0;
     virtual JS::ThrowCompletionOr<String> display(Cell&, const CellTypeMetadata&) const = 0;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const = 0;
     virtual JS::ThrowCompletionOr<JS::Value> js_value(Cell&, const CellTypeMetadata&) const = 0;
+    virtual String metadata_hint(MetadataName) const { return {}; }
     virtual ~CellType() = default;
     virtual ~CellType() = default;
 
 
     const String& name() const { return m_name; }
     const String& name() const { return m_name; }

+ 3 - 0
Userland/Applications/Spreadsheet/CellTypeDialog.cpp

@@ -153,6 +153,8 @@ void CellTypeDialog::setup_tabs(GUI::TabWidget& tabs, const Vector<Position>& po
             }
             }
 
 
             m_type = CellType::get_by_name(g_types.at(index.row()));
             m_type = CellType::get_by_name(g_types.at(index.row()));
+            if (auto* editor = right_side.find_descendant_of_type_named<GUI::TextEditor>("format_editor"))
+                editor->set_tooltip(m_type->metadata_hint(MetadataName::Format));
         };
         };
 
 
         {
         {
@@ -179,6 +181,7 @@ void CellTypeDialog::setup_tabs(GUI::TabWidget& tabs, const Vector<Position>& po
             auto& checkbox = right_side.add<GUI::CheckBox>("Override display format");
             auto& checkbox = right_side.add<GUI::CheckBox>("Override display format");
             auto& editor = right_side.add<GUI::TextEditor>();
             auto& editor = right_side.add<GUI::TextEditor>();
             checkbox.set_checked(!m_format.is_empty());
             checkbox.set_checked(!m_format.is_empty());
+            editor.set_name("format_editor");
             editor.set_should_hide_unnecessary_scrollbars(true);
             editor.set_should_hide_unnecessary_scrollbars(true);
             editor.set_enabled(!m_format.is_empty());
             editor.set_enabled(!m_format.is_empty());
             editor.set_text(m_format);
             editor.set_text(m_format);