summaryrefslogtreecommitdiffstats
path: root/mojo/examples/media_viewer/media_viewer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/examples/media_viewer/media_viewer.cc')
-rw-r--r--mojo/examples/media_viewer/media_viewer.cc210
1 files changed, 201 insertions, 9 deletions
diff --git a/mojo/examples/media_viewer/media_viewer.cc b/mojo/examples/media_viewer/media_viewer.cc
index b727b59..e4ea4c6 100644
--- a/mojo/examples/media_viewer/media_viewer.cc
+++ b/mojo/examples/media_viewer/media_viewer.cc
@@ -7,6 +7,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "mojo/examples/media_viewer/media_viewer.mojom.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
@@ -16,17 +18,170 @@
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
+#include "mojo/views/native_widget_view_manager.h"
+#include "mojo/views/views_init.h"
+#include "skia/ext/platform_canvas.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/painter.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
namespace mojo {
namespace examples {
class MediaViewer;
+class CustomButtonBorder: public views::Border {
+ public:
+ CustomButtonBorder()
+ : normal_painter_(CreatePainter(SkColorSetRGB(0x80, 0x80, 0x80),
+ SkColorSetRGB(0xC0, 0xC0, 0xC0))),
+ hot_painter_(CreatePainter(SkColorSetRGB(0xA0, 0xA0, 0xA0),
+ SkColorSetRGB(0xD0, 0xD0, 0xD0))),
+ pushed_painter_(CreatePainter(SkColorSetRGB(0x80, 0x80, 0x80),
+ SkColorSetRGB(0x90, 0x90, 0x90))),
+ insets_(2, 6, 2, 6) {
+ }
+ virtual ~CustomButtonBorder() {}
+
+ private:
+ // Overridden from views::Border:
+ virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE {
+ const views::LabelButton* button =
+ static_cast<const views::LabelButton*>(&view);
+ views::Button::ButtonState state = button->state();
+
+ views::Painter* painter = normal_painter_.get();
+ if (state == views::Button::STATE_HOVERED) {
+ painter = hot_painter_.get();
+ } else if (state == views::Button::STATE_PRESSED) {
+ painter = pushed_painter_.get();
+ }
+ painter->Paint(canvas, view.size());
+ }
+
+ virtual gfx::Insets GetInsets() const OVERRIDE {
+ return insets_;
+ }
+
+ virtual gfx::Size GetMinimumSize() const OVERRIDE {
+ gfx::Size size;
+ if (normal_painter_)
+ size.SetToMax(normal_painter_->GetMinimumSize());
+ if (hot_painter_)
+ size.SetToMax(hot_painter_->GetMinimumSize());
+ if (pushed_painter_)
+ size.SetToMax(pushed_painter_->GetMinimumSize());
+ return size;
+ }
+
+ scoped_ptr<views::Painter> CreatePainter(SkColor border, SkColor background) {
+ skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas(
+ 64, 64, false)));
+ SkPaint paint;
+ paint.setColor(background);
+ canvas->drawRoundRect(SkRect::MakeWH(63, 63), 2, 2, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(border);
+ canvas->drawRoundRect(SkRect::MakeWH(63, 63), 2, 2, paint);
+
+ return scoped_ptr<views::Painter>(
+ views::Painter::CreateImagePainter(
+ gfx::ImageSkia::CreateFrom1xBitmap(
+ skia::GetTopDevice(*canvas)->accessBitmap(true)),
+ gfx::Insets(5, 5, 5, 5)));
+ }
+
+ scoped_ptr<views::Painter> normal_painter_;
+ scoped_ptr<views::Painter> hot_painter_;
+ scoped_ptr<views::Painter> pushed_painter_;
+
+ gfx::Insets insets_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomButtonBorder);
+};
+
+class ControlPanel : public views::ButtonListener {
+ public:
+ enum ControlType {
+ CONTROL_ZOOM_IN,
+ CONTROL_ACTUAL_SIZE,
+ CONTROL_ZOOM_OUT,
+ CONTROL_COUNT,
+ };
+
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ virtual void ButtonPressed(ControlType type) = 0;
+ };
+
+ ControlPanel(Delegate* delegate) : delegate_(delegate), buttons_() {}
+
+ virtual ~ControlPanel() {}
+
+ void Initialize(view_manager::Node* node) {
+ const char* kNames[] = { "Zoom In", "Actual Size", "Zoom Out" };
+
+ views::WidgetDelegateView* widget_delegate = new views::WidgetDelegateView;
+
+ widget_delegate->GetContentsView()->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 5, 2, 5));
+
+ for (int type = 0; type < CONTROL_COUNT; ++type) {
+ views::Button* button = new views::LabelButton(
+ this, base::ASCIIToUTF16(kNames[type]));
+ button->SetBorder(scoped_ptr<views::Border>(new CustomButtonBorder));
+ buttons_[type] = button;
+ widget_delegate->GetContentsView()->AddChildView(button);
+ }
+
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(
+ views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.native_widget = new NativeWidgetViewManager(widget, node);
+ params.delegate = widget_delegate;
+ params.bounds = gfx::Rect(node->bounds().width(), node->bounds().height());
+ params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
+ widget->Init(params);
+ widget->Show();
+ }
+
+ private:
+ // Overridden from views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ for (int i = 0; i < CONTROL_COUNT; ++i) {
+ if (sender == buttons_[i]) {
+ delegate_->ButtonPressed(static_cast<ControlType>(i));
+ return;
+ }
+ }
+ }
+
+ Delegate* delegate_;
+ views::Button* buttons_[CONTROL_COUNT];
+
+ DISALLOW_COPY_AND_ASSIGN(ControlPanel);
+};
+
class NavigatorImpl : public InterfaceImpl<navigation::Navigator> {
public:
- explicit NavigatorImpl(ApplicationConnection* connection,
- MediaViewer* viewer) : viewer_(viewer) {}
+ NavigatorImpl(ApplicationConnection* connection,
+ MediaViewer* viewer) : viewer_(viewer) {}
virtual ~NavigatorImpl() {}
private:
@@ -42,11 +197,14 @@ class NavigatorImpl : public InterfaceImpl<navigation::Navigator> {
};
class MediaViewer : public ApplicationDelegate,
- public view_manager::ViewManagerDelegate {
+ public view_manager::ViewManagerDelegate,
+ public ControlPanel::Delegate {
public:
MediaViewer() : app_(NULL),
+ view_manager_(NULL),
+ control_node_(NULL),
content_node_(NULL),
- view_manager_(NULL) {
+ control_panel_(this) {
handler_map_["image/png"] = "mojo:mojo_png_viewer";
}
@@ -66,7 +224,6 @@ class MediaViewer : public ApplicationDelegate,
return;
}
- // TODO(yzshen): provide media control UI.
std::string handler = GetHandlerForContentType(
response_details->response->mime_type);
if (handler.empty())
@@ -80,6 +237,10 @@ class MediaViewer : public ApplicationDelegate,
navigator->Navigate(content_node_->id(), navigation_details.Pass(),
response_details.Pass());
}
+
+ // TODO(yzshen): determine the set of controls to show based on what
+ // interfaces the embedded app provides.
+ app_->ConnectToService(handler, &zoomable_media_);
}
private:
@@ -95,6 +256,7 @@ class MediaViewer : public ApplicationDelegate,
// Overridden from ApplicationDelegate:
virtual void Initialize(ApplicationImpl* app) OVERRIDE {
app_ = app;
+ views_init_.reset(new ViewsInit);
}
virtual bool ConfigureIncomingConnection(ApplicationConnection* connection)
@@ -108,11 +270,20 @@ class MediaViewer : public ApplicationDelegate,
virtual void OnRootAdded(view_manager::ViewManager* view_manager,
view_manager::Node* root) OVERRIDE {
view_manager_ = view_manager;
+
+ control_node_ = view_manager::Node::Create(view_manager_);
+ root->AddChild(control_node_);
+ gfx::Rect control_bounds(root->bounds().width(), 28);
+ control_node_->SetBounds(control_bounds);
+ control_node_->SetActiveView(view_manager::View::Create(view_manager_));
+
+ control_panel_.Initialize(control_node_);
+
content_node_ = view_manager::Node::Create(view_manager_);
root->AddChild(content_node_);
-
- gfx::Rect bounds(root->bounds().size());
- content_node_->SetBounds(bounds);
+ gfx::Rect content_bounds(0, control_bounds.height(), root->bounds().width(),
+ root->bounds().height() - control_bounds.height());
+ content_node_->SetBounds(content_bounds);
if (pending_navigate_request_) {
scoped_ptr<PendingNavigateRequest> request(
@@ -123,14 +294,35 @@ class MediaViewer : public ApplicationDelegate,
}
}
+ // Overridden from ControlPanel::Delegate:
+ virtual void ButtonPressed(ControlPanel::ControlType type) OVERRIDE {
+ switch (type) {
+ case ControlPanel::CONTROL_ZOOM_IN:
+ zoomable_media_->ZoomIn();
+ break;
+ case ControlPanel::CONTROL_ACTUAL_SIZE:
+ zoomable_media_->ZoomToActualSize();
+ break;
+ case ControlPanel::CONTROL_ZOOM_OUT:
+ zoomable_media_->ZoomOut();
+ break;
+ default:
+ NOTIMPLEMENTED();
+ }
+ }
+
std::string GetHandlerForContentType(const std::string& content_type) {
HandlerMap::const_iterator it = handler_map_.find(content_type);
return it != handler_map_.end() ? it->second : std::string();
}
ApplicationImpl* app_;
- view_manager::Node* content_node_;
+ scoped_ptr<ViewsInit> views_init_;
view_manager::ViewManager* view_manager_;
+ view_manager::Node* control_node_;
+ view_manager::Node* content_node_;
+ ControlPanel control_panel_;
+ ZoomableMediaPtr zoomable_media_;
HandlerMap handler_map_;
scoped_ptr<PendingNavigateRequest> pending_navigate_request_;