summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-28 10:57:09 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-28 10:57:09 +0100
commitdc9f8a936158b586362cee689b26e095074e59bc (patch)
tree81d14ba66f69f165f46b13dd4025eb08f1c75660
parentb3ae1163efa0324f2062e12bba69463a01d63827 (diff)
downloadserenity-dc9f8a936158b586362cee689b26e095074e59bc.zip
LibGUI: Take ProcessManager's process view and turn it into GTableView.
Make it sufficiently generic that it can be reused for any table data. :^)
-rw-r--r--Applications/ProcessManager/Makefile2
-rw-r--r--Applications/ProcessManager/ProcessTableModel.cpp2
-rw-r--r--Applications/ProcessManager/ProcessTableView.cpp35
-rw-r--r--Applications/ProcessManager/ProcessTableView.h24
-rw-r--r--Applications/ProcessManager/ProcessView.h37
-rw-r--r--Applications/ProcessManager/main.cpp10
-rw-r--r--LibGUI/GTableModel.cpp33
-rw-r--r--LibGUI/GTableModel.h20
-rw-r--r--LibGUI/GTableView.cpp (renamed from Applications/ProcessManager/ProcessView.cpp)62
-rw-r--r--LibGUI/GTableView.h34
-rw-r--r--LibGUI/Makefile2
11 files changed, 173 insertions, 88 deletions
diff --git a/Applications/ProcessManager/Makefile b/Applications/ProcessManager/Makefile
index b996d9443b..75c2566320 100644
--- a/Applications/ProcessManager/Makefile
+++ b/Applications/ProcessManager/Makefile
@@ -1,6 +1,6 @@
OBJS = \
ProcessTableModel.o \
- ProcessView.o \
+ ProcessTableView.o \
main.o
APP = ProcessManager
diff --git a/Applications/ProcessManager/ProcessTableModel.cpp b/Applications/ProcessManager/ProcessTableModel.cpp
index c94bc8fd45..28abcde9b1 100644
--- a/Applications/ProcessManager/ProcessTableModel.cpp
+++ b/Applications/ProcessManager/ProcessTableModel.cpp
@@ -141,6 +141,8 @@ void ProcessTableModel::update()
}
for (auto pid : pids_to_remove)
m_processes.remove(pid);
+
+ did_update();
}
pid_t ProcessTableModel::selected_pid() const
diff --git a/Applications/ProcessManager/ProcessTableView.cpp b/Applications/ProcessManager/ProcessTableView.cpp
new file mode 100644
index 0000000000..0e761c852c
--- /dev/null
+++ b/Applications/ProcessManager/ProcessTableView.cpp
@@ -0,0 +1,35 @@
+#include "ProcessTableView.h"
+#include "ProcessTableModel.h"
+
+
+ProcessTableView::ProcessTableView(GWidget* parent)
+ : GTableView(parent)
+{
+ set_model(make<ProcessTableModel>());
+ start_timer(1000);
+ model().update();
+}
+
+ProcessTableView::~ProcessTableView()
+{
+}
+
+void ProcessTableView::timer_event(GTimerEvent&)
+{
+ model().update();
+}
+
+pid_t ProcessTableView::selected_pid() const
+{
+ return model().selected_pid();
+}
+
+inline ProcessTableModel& ProcessTableView::model()
+{
+ return static_cast<ProcessTableModel&>(*GTableView::model());
+}
+
+inline const ProcessTableModel& ProcessTableView::model() const
+{
+ return static_cast<const ProcessTableModel&>(*GTableView::model());
+}
diff --git a/Applications/ProcessManager/ProcessTableView.h b/Applications/ProcessManager/ProcessTableView.h
new file mode 100644
index 0000000000..d1d823a6e4
--- /dev/null
+++ b/Applications/ProcessManager/ProcessTableView.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <LibGUI/GTableView.h>
+#include <AK/Function.h>
+#include <unistd.h>
+
+class ProcessTableModel;
+
+class ProcessTableView final : public GTableView {
+public:
+ explicit ProcessTableView(GWidget* parent);
+ virtual ~ProcessTableView() override;
+
+ pid_t selected_pid() const;
+
+ Function<void(String)> on_status_message;
+
+private:
+ virtual void timer_event(GTimerEvent&) override;
+
+ ProcessTableModel& model();
+ const ProcessTableModel& model() const;
+};
+
diff --git a/Applications/ProcessManager/ProcessView.h b/Applications/ProcessManager/ProcessView.h
deleted file mode 100644
index 99e9bd79bd..0000000000
--- a/Applications/ProcessManager/ProcessView.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#include <LibGUI/GWidget.h>
-#include <AK/Function.h>
-#include <AK/HashMap.h>
-
-class GScrollBar;
-class ProcessTableModel;
-
-class ProcessView final : public GWidget {
-public:
- ProcessView(GWidget* parent);
- virtual ~ProcessView() override;
-
- void reload();
-
- Function<void(String)> on_status_message;
-
- int header_height() const { return 16; }
- int item_height() const { return 16; }
- int item_count() const;
-
- pid_t selected_pid() const;
-
-private:
- virtual void paint_event(GPaintEvent&) override;
- virtual void resize_event(GResizeEvent&) override;
- virtual void mousedown_event(GMouseEvent&) override;
- virtual void timer_event(GTimerEvent&) override;
-
- void set_status_message(String&&);
- Rect row_rect(int item_index) const;
-
- RetainPtr<GraphicsBitmap> m_process_icon;
- GScrollBar* m_scrollbar { nullptr };
- OwnPtr<ProcessTableModel> m_model;
-};
diff --git a/Applications/ProcessManager/main.cpp b/Applications/ProcessManager/main.cpp
index cf6b4faa7e..8e1b8deae2 100644
--- a/Applications/ProcessManager/main.cpp
+++ b/Applications/ProcessManager/main.cpp
@@ -9,7 +9,7 @@
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
-#include "ProcessView.h"
+#include "ProcessTableView.h"
int main(int argc, char** argv)
{
@@ -19,14 +19,14 @@ int main(int argc, char** argv)
widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
auto* toolbar = new GToolBar(widget);
- auto* process_view = new ProcessView(widget);
+ auto* process_table_view = new ProcessTableView(widget);
auto* statusbar = new GStatusBar(widget);
- process_view->on_status_message = [statusbar] (String message) {
+ process_table_view->on_status_message = [statusbar] (String message) {
statusbar->set_text(move(message));
};
- auto kill_action = GAction::create("Kill process", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/kill16.rgb", { 16, 16 }), [process_view] (const GAction&) {
- pid_t pid = process_view->selected_pid();
+ auto kill_action = GAction::create("Kill process", GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/kill16.rgb", { 16, 16 }), [process_table_view] (const GAction&) {
+ pid_t pid = process_table_view->selected_pid();
if (pid != -1)
kill(pid, SIGKILL);
});
diff --git a/LibGUI/GTableModel.cpp b/LibGUI/GTableModel.cpp
new file mode 100644
index 0000000000..c45d615558
--- /dev/null
+++ b/LibGUI/GTableModel.cpp
@@ -0,0 +1,33 @@
+#include <LibGUI/GTableModel.h>
+#include <LibGUI/GTableView.h>
+
+GTableModel::GTableModel()
+{
+}
+
+GTableModel::~GTableModel()
+{
+}
+
+void GTableModel::register_view(Badge<GTableView>, GTableView& view)
+{
+ m_views.set(&view);
+}
+
+void GTableModel::unregister_view(Badge<GTableView>, GTableView& view)
+{
+ m_views.remove(&view);
+}
+
+void GTableModel::for_each_view(Function<void(GTableView&)> callback)
+{
+ for (auto* view : m_views)
+ callback(*view);
+}
+
+void GTableModel::did_update()
+{
+ for_each_view([] (GTableView& view) {
+ view.did_update_model();
+ });
+}
diff --git a/LibGUI/GTableModel.h b/LibGUI/GTableModel.h
index 365bc84bf6..c1548718da 100644
--- a/LibGUI/GTableModel.h
+++ b/LibGUI/GTableModel.h
@@ -1,12 +1,16 @@
#pragma once
#include <AK/AKString.h>
+#include <AK/Badge.h>
+#include <AK/Function.h>
+#include <AK/HashTable.h>
#include <LibGUI/GModelIndex.h>
+class GTableView;
+
class GTableModel {
public:
- GTableModel() { }
- virtual ~GTableModel() { }
+ virtual ~GTableModel();
virtual int row_count() const = 0;
virtual int column_count() const = 0;
@@ -22,4 +26,16 @@ public:
{
return index.row() >= 0 && index.row() < row_count() && index.column() >= 0 && index.column() < column_count();
}
+
+ void register_view(Badge<GTableView>, GTableView&);
+ void unregister_view(Badge<GTableView>, GTableView&);
+
+protected:
+ GTableModel();
+
+ void for_each_view(Function<void(GTableView&)>);
+ void did_update();
+
+private:
+ HashTable<GTableView*> m_views;
};
diff --git a/Applications/ProcessManager/ProcessView.cpp b/LibGUI/GTableView.cpp
index 7fbb68410d..0f98f1eac8 100644
--- a/Applications/ProcessManager/ProcessView.cpp
+++ b/LibGUI/GTableView.cpp
@@ -1,65 +1,52 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <AK/FileSystemPath.h>
-#include <AK/HashMap.h>
-#include <SharedGraphics/GraphicsBitmap.h>
-#include <SharedGraphics/Painter.h>
+#include <LibGUI/GTableView.h>
+#include <LibGUI/GTableModel.h>
#include <LibGUI/GScrollBar.h>
-#include "ProcessTableModel.h"
-#include "ProcessView.h"
-
-static HashMap<unsigned, String>* s_usernames;
+#include <SharedGraphics/Painter.h>
-ProcessView::ProcessView(GWidget* parent)
+GTableView::GTableView(GWidget* parent)
: GWidget(parent)
{
- m_process_icon = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/gear16.rgb", { 16, 16 });
-
m_scrollbar = new GScrollBar(Orientation::Vertical, this);
m_scrollbar->set_step(4);
m_scrollbar->set_big_step(30);
m_scrollbar->on_change = [this] (int) {
update();
};
-
- m_model = make<ProcessTableModel>();
-
- start_timer(1000);
- reload();
}
-ProcessView::~ProcessView()
+GTableView::~GTableView()
{
}
-void ProcessView::timer_event(GTimerEvent&)
+void GTableView::set_model(OwnPtr<GTableModel>&& model)
{
- reload();
+ if (model.ptr() == m_model.ptr())
+ return;
+ if (m_model)
+ m_model->unregister_view(Badge<GTableView>(), *this);
+ m_model = move(model);
+ if (m_model)
+ m_model->register_view(Badge<GTableView>(), *this);
}
-void ProcessView::resize_event(GResizeEvent& event)
+void GTableView::resize_event(GResizeEvent& event)
{
m_scrollbar->set_relative_rect(event.size().width() - m_scrollbar->preferred_size().width(), 0, m_scrollbar->preferred_size().width(), event.size().height());
}
-void ProcessView::reload()
+void GTableView::did_update_model()
{
- m_model->update();
-
int excess_height = max(0, (item_count() * item_height()) - height());
m_scrollbar->set_range(0, excess_height);
-
- set_status_message(String::format("%d processes", item_count()));
update();
}
-Rect ProcessView::row_rect(int item_index) const
+Rect GTableView::row_rect(int item_index) const
{
return { 0, header_height() + (item_index * item_height()), width(), item_height() };
}
-void ProcessView::mousedown_event(GMouseEvent& event)
+void GTableView::mousedown_event(GMouseEvent& event)
{
auto adjusted_position = event.position().translated(0, m_scrollbar->value());
if (event.button() == GMouseButton::Left) {
@@ -72,7 +59,7 @@ void ProcessView::mousedown_event(GMouseEvent& event)
}
}
-void ProcessView::paint_event(GPaintEvent&)
+void GTableView::paint_event(GPaintEvent&)
{
Painter painter(*this);
@@ -124,18 +111,7 @@ void ProcessView::paint_event(GPaintEvent&)
painter.draw_line({ 0, header_height() - 1 }, { width() - 1, header_height() - 1 }, Color::DarkGray);
}
-void ProcessView::set_status_message(String&& message)
-{
- if (on_status_message)
- on_status_message(move(message));
-}
-
-int ProcessView::item_count() const
+int GTableView::item_count() const
{
return m_model->row_count();
}
-
-pid_t ProcessView::selected_pid() const
-{
- return m_model->selected_pid();
-}
diff --git a/LibGUI/GTableView.h b/LibGUI/GTableView.h
new file mode 100644
index 0000000000..674014ce97
--- /dev/null
+++ b/LibGUI/GTableView.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <LibGUI/GWidget.h>
+#include <AK/Function.h>
+#include <AK/HashMap.h>
+
+class GScrollBar;
+class GTableModel;
+
+class GTableView : public GWidget {
+public:
+ explicit GTableView(GWidget* parent);
+ virtual ~GTableView() override;
+
+ virtual int header_height() const { return 16; }
+ virtual int item_height() const { return 16; }
+
+ void set_model(OwnPtr<GTableModel>&&);
+ GTableModel* model() { return m_model.ptr(); }
+ const GTableModel* model() const { return m_model.ptr(); }
+
+ void did_update_model();
+
+private:
+ virtual void paint_event(GPaintEvent&) override;
+ virtual void resize_event(GResizeEvent&) override;
+ virtual void mousedown_event(GMouseEvent&) override;
+
+ int item_count() const;
+ Rect row_rect(int item_index) const;
+
+ GScrollBar* m_scrollbar { nullptr };
+ OwnPtr<GTableModel> m_model;
+};
diff --git a/LibGUI/Makefile b/LibGUI/Makefile
index f3ac6e262b..b324290a32 100644
--- a/LibGUI/Makefile
+++ b/LibGUI/Makefile
@@ -28,6 +28,8 @@ LIBGUI_OBJS = \
GAction.o \
GFontDatabase.o \
GToolBar.o \
+ GTableView.o \
+ GTableModel.o \
GWindow.o
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)