소스 검색

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
 }
 
+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 JS::ThrowCompletionOr<String> display(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
@@ -25,4 +29,14 @@ JS::ThrowCompletionOr<JS::Value> IdentityCell::js_value(Cell& cell, const CellTy
     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 JS::ThrowCompletionOr<String> display(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 JS::ThrowCompletionOr<String> display(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);
 }
 
+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 JS::ThrowCompletionOr<String> display(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;
 };
 
+enum class MetadataName {
+    Length,
+    Format,
+    Alignment,
+    StaticFormat,
+};
+
 class CellType {
 public:
     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<JS::Value> js_value(Cell&, const CellTypeMetadata&) const = 0;
+    virtual String metadata_hint(MetadataName) const { return {}; }
     virtual ~CellType() = default;
 
     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()));
+            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& editor = right_side.add<GUI::TextEditor>();
             checkbox.set_checked(!m_format.is_empty());
+            editor.set_name("format_editor");
             editor.set_should_hide_unnecessary_scrollbars(true);
             editor.set_enabled(!m_format.is_empty());
             editor.set_text(m_format);