| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/macros.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "examples/media_viewer/media_viewer.mojom.h" |
| #include "mojo/application/application_runner_chromium.h" |
| #include "mojo/public/c/system/main.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" |
| #include "mojo/public/cpp/application/interface_factory_impl.h" |
| #include "mojo/public/cpp/bindings/interface_impl.h" |
| #include "mojo/services/public/interfaces/navigation/navigation.mojom.h" |
| #include "mojo/services/view_manager/public/cpp/view.h" |
| #include "mojo/services/view_manager/public/cpp/view_manager.h" |
| #include "mojo/services/view_manager/public/cpp/view_manager_client_factory.h" |
| #include "mojo/services/view_manager/public/cpp/view_manager_delegate.h" |
| #include "mojo/services/view_manager/public/cpp/view_observer.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/gfx/image/image_skia.h" |
| #include "ui/views/background.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; |
| }; |
| |
| explicit ControlPanel(Delegate* delegate) |
| : delegate_(delegate), shell_(nullptr), buttons_() {} |
| |
| virtual ~ControlPanel() {} |
| |
| void Initialize(View* view, Shell* shell) { |
| 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)); |
| |
| widget_delegate->GetContentsView()->set_background( |
| views::Background::CreateSolidBackground(SK_ColorLTGRAY)); |
| |
| 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, shell, view); |
| params.delegate = widget_delegate; |
| params.bounds = gfx::Rect(view->bounds().width, view->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_; |
| Shell* shell_; |
| views::Button* buttons_[CONTROL_COUNT]; |
| |
| DISALLOW_COPY_AND_ASSIGN(ControlPanel); |
| }; |
| |
| class MediaViewer |
| : public ApplicationDelegate, |
| public ViewManagerDelegate, |
| public ControlPanel::Delegate, |
| public ViewObserver { |
| public: |
| MediaViewer() |
| : shell_(nullptr), |
| app_(NULL), |
| view_manager_(NULL), |
| root_view_(NULL), |
| control_view_(NULL), |
| content_view_(NULL), |
| control_panel_(this) { |
| handler_map_["image/png"] = "mojo:png_viewer"; |
| } |
| |
| virtual ~MediaViewer() { |
| if (root_view_) |
| root_view_->RemoveObserver(this); |
| } |
| |
| private: |
| typedef std::map<std::string, std::string> HandlerMap; |
| |
| |
| // Overridden from ApplicationDelegate: |
| virtual void Initialize(ApplicationImpl* app) override { |
| shell_ = app->shell(); |
| view_manager_client_factory_.reset( |
| new ViewManagerClientFactory(app->shell(), this)); |
| app_ = app; |
| views_init_.reset(new ViewsInit); |
| } |
| |
| virtual bool ConfigureIncomingConnection(ApplicationConnection* connection) |
| override { |
| connection->AddService(view_manager_client_factory_.get()); |
| return true; |
| } |
| |
| void LayoutViews() { |
| View* root = content_view_->parent(); |
| Rect control_bounds; |
| control_bounds.width = root->bounds().width; |
| control_bounds.height = 28; |
| control_view_->SetBounds(control_bounds); |
| Rect content_bounds; |
| content_bounds.y = control_bounds.height; |
| content_bounds.width = root->bounds().width; |
| content_bounds.height = root->bounds().height - control_bounds.height; |
| content_view_->SetBounds(content_bounds); |
| } |
| |
| // Overridden from ViewManagerDelegate: |
| virtual void OnEmbed(ViewManager* view_manager, |
| View* root, |
| ServiceProviderImpl* exported_services, |
| scoped_ptr<ServiceProvider> imported_services) override { |
| root_view_ = root; |
| view_manager_ = view_manager; |
| |
| control_view_ = View::Create(view_manager_); |
| control_view_->SetVisible(true); |
| root_view_->AddChild(control_view_); |
| |
| content_view_ = View::Create(view_manager_); |
| content_view_->SetVisible(true); |
| root_view_->AddChild(content_view_); |
| |
| control_panel_.Initialize(control_view_, shell_); |
| |
| LayoutViews(); |
| root_view_->AddObserver(this); |
| |
| content_view_->Embed("TODO"); |
| } |
| |
| virtual void OnViewManagerDisconnected( |
| ViewManager* view_manager) override { |
| DCHECK_EQ(view_manager_, view_manager); |
| view_manager_ = NULL; |
| base::MessageLoop::current()->Quit(); |
| } |
| |
| // 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(); |
| } |
| } |
| |
| // ViewObserver: |
| virtual void OnViewBoundsChanged(View* view, |
| const Rect& old_bounds, |
| const Rect& new_bounds) override { |
| LayoutViews(); |
| } |
| virtual void OnViewDestroyed(View* view) override { |
| DCHECK_EQ(view, root_view_); |
| view->RemoveObserver(this); |
| root_view_ = NULL; |
| } |
| |
| 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(); |
| } |
| |
| Shell* shell_; |
| |
| scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; |
| |
| ApplicationImpl* app_; |
| scoped_ptr<ViewsInit> views_init_; |
| ViewManager* view_manager_; |
| View* root_view_; |
| View* control_view_; |
| View* content_view_; |
| ControlPanel control_panel_; |
| ZoomableMediaPtr zoomable_media_; |
| HandlerMap handler_map_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MediaViewer); |
| }; |
| |
| } // namespace examples |
| } // namespace mojo |
| |
| MojoResult MojoMain(MojoHandle shell_handle) { |
| mojo::ApplicationRunnerChromium runner(new mojo::examples::MediaViewer); |
| return runner.Run(shell_handle); |
| } |