Home | History | Annotate | Download | only in media_viewer
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <map>
      6 #include <string>
      7 
      8 #include "base/macros.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "mojo/application/application_runner_chromium.h"
     12 #include "mojo/examples/media_viewer/media_viewer.mojom.h"
     13 #include "mojo/public/c/system/main.h"
     14 #include "mojo/public/cpp/application/application_connection.h"
     15 #include "mojo/public/cpp/application/application_delegate.h"
     16 #include "mojo/public/cpp/application/application_impl.h"
     17 #include "mojo/public/cpp/application/interface_factory_impl.h"
     18 #include "mojo/public/cpp/bindings/interface_impl.h"
     19 #include "mojo/services/public/cpp/view_manager/view.h"
     20 #include "mojo/services/public/cpp/view_manager/view_manager.h"
     21 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h"
     22 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
     23 #include "mojo/services/public/cpp/view_manager/view_observer.h"
     24 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
     25 #include "mojo/views/native_widget_view_manager.h"
     26 #include "mojo/views/views_init.h"
     27 #include "skia/ext/platform_canvas.h"
     28 #include "skia/ext/refptr.h"
     29 #include "third_party/skia/include/core/SkBitmap.h"
     30 #include "third_party/skia/include/core/SkCanvas.h"
     31 #include "third_party/skia/include/core/SkColor.h"
     32 #include "third_party/skia/include/core/SkPaint.h"
     33 #include "third_party/skia/include/core/SkRect.h"
     34 #include "ui/gfx/canvas.h"
     35 #include "ui/gfx/geometry/insets.h"
     36 #include "ui/gfx/geometry/rect.h"
     37 #include "ui/views/background.h"
     38 #include "ui/views/border.h"
     39 #include "ui/views/controls/button/button.h"
     40 #include "ui/views/controls/button/label_button.h"
     41 #include "ui/views/layout/box_layout.h"
     42 #include "ui/views/painter.h"
     43 #include "ui/views/widget/widget.h"
     44 #include "ui/views/widget/widget_delegate.h"
     45 
     46 namespace mojo {
     47 namespace examples {
     48 
     49 class MediaViewer;
     50 
     51 class CustomButtonBorder: public views::Border {
     52  public:
     53   CustomButtonBorder()
     54       : normal_painter_(CreatePainter(SkColorSetRGB(0x80, 0x80, 0x80),
     55                                       SkColorSetRGB(0xC0, 0xC0, 0xC0))),
     56         hot_painter_(CreatePainter(SkColorSetRGB(0xA0, 0xA0, 0xA0),
     57                                    SkColorSetRGB(0xD0, 0xD0, 0xD0))),
     58         pushed_painter_(CreatePainter(SkColorSetRGB(0x80, 0x80, 0x80),
     59                                       SkColorSetRGB(0x90, 0x90, 0x90))),
     60         insets_(2, 6, 2, 6) {
     61   }
     62   virtual ~CustomButtonBorder() {}
     63 
     64  private:
     65   // Overridden from views::Border:
     66   virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE {
     67     const views::LabelButton* button =
     68         static_cast<const views::LabelButton*>(&view);
     69     views::Button::ButtonState state = button->state();
     70 
     71     views::Painter* painter = normal_painter_.get();
     72     if (state == views::Button::STATE_HOVERED) {
     73       painter = hot_painter_.get();
     74     } else if (state == views::Button::STATE_PRESSED) {
     75       painter = pushed_painter_.get();
     76     }
     77     painter->Paint(canvas, view.size());
     78   }
     79 
     80   virtual gfx::Insets GetInsets() const OVERRIDE {
     81     return insets_;
     82   }
     83 
     84   virtual gfx::Size GetMinimumSize() const OVERRIDE {
     85     gfx::Size size;
     86     if (normal_painter_)
     87       size.SetToMax(normal_painter_->GetMinimumSize());
     88     if (hot_painter_)
     89       size.SetToMax(hot_painter_->GetMinimumSize());
     90     if (pushed_painter_)
     91       size.SetToMax(pushed_painter_->GetMinimumSize());
     92     return size;
     93   }
     94 
     95   scoped_ptr<views::Painter> CreatePainter(SkColor border, SkColor background) {
     96     skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas(
     97         64, 64, false)));
     98     SkPaint paint;
     99     paint.setColor(background);
    100     canvas->drawRoundRect(SkRect::MakeWH(63, 63), 2, 2, paint);
    101     paint.setStyle(SkPaint::kStroke_Style);
    102     paint.setColor(border);
    103     canvas->drawRoundRect(SkRect::MakeWH(63, 63), 2, 2, paint);
    104 
    105     return scoped_ptr<views::Painter>(
    106         views::Painter::CreateImagePainter(
    107             gfx::ImageSkia::CreateFrom1xBitmap(
    108                 skia::GetTopDevice(*canvas)->accessBitmap(true)),
    109             gfx::Insets(5, 5, 5, 5)));
    110   }
    111 
    112   scoped_ptr<views::Painter> normal_painter_;
    113   scoped_ptr<views::Painter> hot_painter_;
    114   scoped_ptr<views::Painter> pushed_painter_;
    115 
    116   gfx::Insets insets_;
    117 
    118   DISALLOW_COPY_AND_ASSIGN(CustomButtonBorder);
    119 };
    120 
    121 class ControlPanel : public views::ButtonListener {
    122  public:
    123   enum ControlType {
    124     CONTROL_ZOOM_IN,
    125     CONTROL_ACTUAL_SIZE,
    126     CONTROL_ZOOM_OUT,
    127     CONTROL_COUNT,
    128   };
    129 
    130   class Delegate {
    131    public:
    132     virtual ~Delegate() {}
    133 
    134     virtual void ButtonPressed(ControlType type) = 0;
    135   };
    136 
    137   ControlPanel(Delegate* delegate) : delegate_(delegate), buttons_() {}
    138 
    139   virtual ~ControlPanel() {}
    140 
    141   void Initialize(View* view) {
    142     const char* kNames[] = { "Zoom In", "Actual Size", "Zoom Out" };
    143 
    144     views::WidgetDelegateView* widget_delegate = new views::WidgetDelegateView;
    145 
    146     widget_delegate->GetContentsView()->SetLayoutManager(
    147         new views::BoxLayout(views::BoxLayout::kHorizontal, 5, 2, 5));
    148 
    149     widget_delegate->GetContentsView()->set_background(
    150         views::Background::CreateSolidBackground(SK_ColorLTGRAY));
    151 
    152     for (int type = 0; type < CONTROL_COUNT; ++type) {
    153       views::Button* button = new views::LabelButton(
    154           this, base::ASCIIToUTF16(kNames[type]));
    155       button->SetBorder(scoped_ptr<views::Border>(new CustomButtonBorder));
    156       buttons_[type] = button;
    157       widget_delegate->GetContentsView()->AddChildView(button);
    158     }
    159 
    160     views::Widget* widget = new views::Widget;
    161     views::Widget::InitParams params(
    162         views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    163     params.native_widget = new NativeWidgetViewManager(widget, view);
    164     params.delegate = widget_delegate;
    165     params.bounds = gfx::Rect(view->bounds().width(), view->bounds().height());
    166     params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
    167     widget->Init(params);
    168     widget->Show();
    169   }
    170 
    171  private:
    172   // Overridden from views::ButtonListener:
    173   virtual void ButtonPressed(views::Button* sender,
    174                              const ui::Event& event) OVERRIDE {
    175     for (int i = 0; i < CONTROL_COUNT; ++i) {
    176       if (sender == buttons_[i]) {
    177         delegate_->ButtonPressed(static_cast<ControlType>(i));
    178         return;
    179       }
    180     }
    181   }
    182 
    183   Delegate* delegate_;
    184   views::Button* buttons_[CONTROL_COUNT];
    185 
    186   DISALLOW_COPY_AND_ASSIGN(ControlPanel);
    187 };
    188 
    189 class MediaViewer
    190     : public ApplicationDelegate,
    191       public ViewManagerDelegate,
    192       public ControlPanel::Delegate,
    193       public ViewObserver {
    194  public:
    195   MediaViewer()
    196       : app_(NULL),
    197         view_manager_(NULL),
    198         root_view_(NULL),
    199         control_view_(NULL),
    200         content_view_(NULL),
    201         control_panel_(this) {
    202     handler_map_["image/png"] = "mojo:mojo_png_viewer";
    203   }
    204 
    205   virtual ~MediaViewer() {
    206     if (root_view_)
    207       root_view_->RemoveObserver(this);
    208   }
    209 
    210  private:
    211   typedef std::map<std::string, std::string> HandlerMap;
    212 
    213 
    214   // Overridden from ApplicationDelegate:
    215   virtual void Initialize(ApplicationImpl* app) OVERRIDE {
    216     view_manager_client_factory_.reset(
    217         new ViewManagerClientFactory(app->shell(), this));
    218     app_ = app;
    219     views_init_.reset(new ViewsInit);
    220   }
    221 
    222   virtual bool ConfigureIncomingConnection(ApplicationConnection* connection)
    223       OVERRIDE {
    224     connection->AddService(view_manager_client_factory_.get());
    225     return true;
    226   }
    227 
    228   void LayoutViews() {
    229     View* root = content_view_->parent();
    230     gfx::Rect control_bounds(root->bounds().width(), 28);
    231     control_view_->SetBounds(control_bounds);
    232     gfx::Rect content_bounds(0, control_bounds.height(), root->bounds().width(),
    233                              root->bounds().height() - control_bounds.height());
    234     content_view_->SetBounds(content_bounds);
    235   }
    236 
    237   // Overridden from ViewManagerDelegate:
    238   virtual void OnEmbed(ViewManager* view_manager,
    239                        View* root,
    240                        ServiceProviderImpl* exported_services,
    241                        scoped_ptr<ServiceProvider> imported_services) OVERRIDE {
    242     root_view_ = root;
    243     view_manager_ = view_manager;
    244 
    245     control_view_ = View::Create(view_manager_);
    246     root_view_->AddChild(control_view_);
    247 
    248     content_view_ = View::Create(view_manager_);
    249     root_view_->AddChild(content_view_);
    250 
    251     control_panel_.Initialize(control_view_);
    252 
    253     LayoutViews();
    254     root_view_->AddObserver(this);
    255 
    256     content_view_->Embed("TODO");
    257   }
    258 
    259   virtual void OnViewManagerDisconnected(
    260       ViewManager* view_manager) OVERRIDE {
    261     DCHECK_EQ(view_manager_, view_manager);
    262     view_manager_ = NULL;
    263     base::MessageLoop::current()->Quit();
    264   }
    265 
    266   // Overridden from ControlPanel::Delegate:
    267   virtual void ButtonPressed(ControlPanel::ControlType type) OVERRIDE {
    268     switch (type) {
    269       case ControlPanel::CONTROL_ZOOM_IN:
    270         zoomable_media_->ZoomIn();
    271         break;
    272       case ControlPanel::CONTROL_ACTUAL_SIZE:
    273        zoomable_media_->ZoomToActualSize();
    274         break;
    275       case ControlPanel::CONTROL_ZOOM_OUT:
    276         zoomable_media_->ZoomOut();
    277         break;
    278       default:
    279         NOTIMPLEMENTED();
    280     }
    281   }
    282 
    283   // ViewObserver:
    284   virtual void OnViewBoundsChanged(View* view,
    285                                    const gfx::Rect& old_bounds,
    286                                    const gfx::Rect& new_bounds) OVERRIDE {
    287     LayoutViews();
    288   }
    289   virtual void OnViewDestroyed(View* view) OVERRIDE {
    290     DCHECK_EQ(view, root_view_);
    291     view->RemoveObserver(this);
    292     root_view_ = NULL;
    293   }
    294 
    295   std::string GetHandlerForContentType(const std::string& content_type) {
    296     HandlerMap::const_iterator it = handler_map_.find(content_type);
    297     return it != handler_map_.end() ? it->second : std::string();
    298   }
    299 
    300   scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_;
    301 
    302   ApplicationImpl* app_;
    303   scoped_ptr<ViewsInit> views_init_;
    304   ViewManager* view_manager_;
    305   View* root_view_;
    306   View* control_view_;
    307   View* content_view_;
    308   ControlPanel control_panel_;
    309   ZoomableMediaPtr zoomable_media_;
    310   HandlerMap handler_map_;
    311 
    312   DISALLOW_COPY_AND_ASSIGN(MediaViewer);
    313 };
    314 
    315 }  // namespace examples
    316 }  // namespace mojo
    317 
    318 MojoResult MojoMain(MojoHandle shell_handle) {
    319   mojo::ApplicationRunnerChromium runner(new mojo::examples::MediaViewer);
    320   return runner.Run(shell_handle);
    321 }
    322