Kaynağa Gözat

QuickShow: Allow panning and zooming the image instead of stretching it.

This needs more work and polish, but it's a step in a more pleasant and
useful direction.

Also turn QuickShow into a fully-fledged "application". (By that, I really
just mean giving it its own Applications/ subdirectory.)
Andreas Kling 6 yıl önce
ebeveyn
işleme
eedb4f6b2f

+ 3 - 0
Applications/QuickShow/.gitignore

@@ -0,0 +1,3 @@
+*.o
+*.d
+QuickShow

+ 23 - 0
Applications/QuickShow/Makefile

@@ -0,0 +1,23 @@
+include ../../Makefile.common
+
+OBJS = \
+    QSWidget.o \
+    main.o
+
+APP = QuickShow
+
+DEFINES += -DUSERLAND
+
+all: $(APP)
+
+$(APP): $(OBJS)
+	$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -lcore -lc
+
+.cpp.o:
+	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
+
+-include $(OBJS:%.o=%.d)
+
+clean:
+	@echo "CLEAN"; rm -f $(APP) $(OBJS) *.d
+

+ 85 - 0
Applications/QuickShow/QSWidget.cpp

@@ -0,0 +1,85 @@
+#include "QSWidget.h"
+#include <LibGUI/GPainter.h>
+#include <SharedGraphics/GraphicsBitmap.h>
+
+QSWidget::QSWidget(GWidget* parent)
+    : GFrame(parent)
+{
+    set_frame_shape(FrameShape::Container);
+    set_frame_shadow(FrameShadow::Sunken);
+    set_frame_thickness(2);
+
+    set_background_color(Color::White);
+}
+
+QSWidget::~QSWidget()
+{
+}
+
+void QSWidget::set_bitmap(NonnullRefPtr<GraphicsBitmap> bitmap)
+{
+    set_fill_with_background_color(bitmap->has_alpha_channel());
+    m_bitmap = move(bitmap);
+}
+
+void QSWidget::relayout()
+{
+    Size new_size;
+    float scale_factor = (float)m_scale / 100.0f;
+    new_size.set_width(m_bitmap->width() * scale_factor);
+    new_size.set_height(m_bitmap->height() * scale_factor);
+    m_bitmap_rect.set_size(new_size);
+    update();
+}
+
+void QSWidget::resize_event(GResizeEvent& event)
+{
+    relayout();
+    GWidget::resize_event(event);
+}
+
+void QSWidget::paint_event(GPaintEvent& event)
+{
+    GPainter painter(*this);
+    painter.add_clip_rect(event.rect());
+
+    painter.draw_scaled_bitmap(m_bitmap_rect, *m_bitmap, m_bitmap->rect());
+}
+
+void QSWidget::mousedown_event(GMouseEvent& event)
+{
+    if (event.button() != GMouseButton::Left)
+        return;
+    m_pan_origin = event.position();
+    m_pan_bitmap_origin = m_bitmap_rect.location();
+}
+
+void QSWidget::mouseup_event(GMouseEvent& event)
+{
+    UNUSED_PARAM(event);
+}
+
+void QSWidget::mousemove_event(GMouseEvent& event)
+{
+    if (!(event.buttons() & GMouseButton::Left))
+        return;
+
+    auto delta = event.position() - m_pan_origin;
+    m_bitmap_rect.set_location(m_pan_bitmap_origin.translated(delta));
+    update();
+}
+
+void QSWidget::mousewheel_event(GMouseEvent& event)
+{
+    auto old_scale = m_scale;
+    m_scale += -event.wheel_delta() * 10;
+    if (m_scale < 10)
+        m_scale = 10;
+    if (m_scale > 1000)
+        m_scale = 1000;
+    relayout();
+    if (old_scale != m_scale) {
+        if (on_scale_change)
+            on_scale_change(m_scale);
+    }
+}

+ 32 - 0
Applications/QuickShow/QSWidget.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include <LibGUI/GFrame.h>
+
+class GLabel;
+class QSLabel;
+
+class QSWidget final : public GFrame {
+public:
+    QSWidget(GWidget* parent);
+    virtual ~QSWidget() override;
+
+    void set_bitmap(NonnullRefPtr<GraphicsBitmap>);
+
+    Function<void(int)> on_scale_change;
+
+private:
+    virtual void paint_event(GPaintEvent&) override;
+    virtual void resize_event(GResizeEvent&) override;
+    virtual void mousedown_event(GMouseEvent&) override;
+    virtual void mouseup_event(GMouseEvent&) override;
+    virtual void mousemove_event(GMouseEvent&) override;
+    virtual void mousewheel_event(GMouseEvent&) override;
+
+    void relayout();
+
+    RefPtr<GraphicsBitmap> m_bitmap;
+    Rect m_bitmap_rect;
+    int m_scale { 100 };
+    Point m_pan_origin;
+    Point m_pan_bitmap_origin;
+};

+ 11 - 13
Userland/qs.cpp → Applications/QuickShow/main.cpp

@@ -1,3 +1,4 @@
+#include "QSWidget.h"
 #include <LibGUI/GAction.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GApplication.h>
 #include <LibGUI/GApplication.h>
 #include <LibGUI/GBoxLayout.h>
 #include <LibGUI/GBoxLayout.h>
@@ -51,24 +52,21 @@ int main(int argc, char** argv)
 
 
     auto* window = new GWindow;
     auto* window = new GWindow;
 
 
+    auto update_window_title = [&](int scale) {
+        window->set_title(String::format("QuickShow: %s %s %d%%", path, bitmap->size().to_string().characters(), scale));
+    };
+
     window->set_double_buffering_enabled(false);
     window->set_double_buffering_enabled(false);
-    window->set_title(String::format("QuickShow: %s %s", path, bitmap->size().to_string().characters()));
+    update_window_title(100);
     window->set_rect(200, 200, bitmap->width(), bitmap->height());
     window->set_rect(200, 200, bitmap->width(), bitmap->height());
 
 
-    auto* widget = new GWidget;
+    auto* widget = new QSWidget(nullptr);
+    widget->on_scale_change = [&](int scale) {
+        update_window_title(scale);
+    };
+    widget->set_bitmap(*bitmap);
     window->set_main_widget(widget);
     window->set_main_widget(widget);
 
 
-    if (bitmap->has_alpha_channel()) {
-        widget->set_background_color(Color::White);
-        widget->set_fill_with_background_color(true);
-    }
-
-    widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
-
-    auto* label = new GLabel(widget);
-    label->set_icon(move(bitmap));
-    label->set_should_stretch_icon(true);
-
     window->set_should_exit_event_loop_on_close(true);
     window->set_should_exit_event_loop_on_close(true);
     window->show();
     window->show();
 
 

+ 2 - 0
Kernel/build-root-filesystem.sh

@@ -72,6 +72,7 @@ cp ../Applications/Taskbar/Taskbar mnt/bin/Taskbar
 cp ../Applications/Terminal/Terminal mnt/bin/Terminal
 cp ../Applications/Terminal/Terminal mnt/bin/Terminal
 cp ../Applications/TextEditor/TextEditor mnt/bin/TextEditor
 cp ../Applications/TextEditor/TextEditor mnt/bin/TextEditor
 cp ../Applications/PaintBrush/PaintBrush mnt/bin/PaintBrush
 cp ../Applications/PaintBrush/PaintBrush mnt/bin/PaintBrush
+cp ../Applications/QuickShow/QuickShow mnt/bin/QuickShow
 cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld
 cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld
 cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch
 cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch
 cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery
 cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery
@@ -99,6 +100,7 @@ ln -s VisualBuilder mnt/bin/vb
 ln -s WidgetGallery mnt/bin/wg
 ln -s WidgetGallery mnt/bin/wg
 ln -s TextEditor mnt/bin/te
 ln -s TextEditor mnt/bin/te
 ln -s PaintBrush mnt/bin/pb
 ln -s PaintBrush mnt/bin/pb
+ln -s QuickShow mnt/bin/qs
 echo "done"
 echo "done"
 
 
 # Run local sync script, if it exists
 # Run local sync script, if it exists

+ 1 - 0
Kernel/makeall.sh

@@ -30,6 +30,7 @@ build_targets="$build_targets ../Applications/IRCClient"
 build_targets="$build_targets ../Applications/Taskbar"
 build_targets="$build_targets ../Applications/Taskbar"
 build_targets="$build_targets ../Applications/Downloader"
 build_targets="$build_targets ../Applications/Downloader"
 build_targets="$build_targets ../Applications/PaintBrush"
 build_targets="$build_targets ../Applications/PaintBrush"
+build_targets="$build_targets ../Applications/QuickShow"
 build_targets="$build_targets ../DevTools/VisualBuilder"
 build_targets="$build_targets ../DevTools/VisualBuilder"
 build_targets="$build_targets ../Games/Minesweeper"
 build_targets="$build_targets ../Games/Minesweeper"
 build_targets="$build_targets ../Games/Snake"
 build_targets="$build_targets ../Games/Snake"