diff options
Diffstat (limited to 'mojo/examples/media_viewer/media_viewer.cc')
-rw-r--r-- | mojo/examples/media_viewer/media_viewer.cc | 210 |
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_; |