| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "ash/drag_drop/drag_image_view.h" | |
| 6 | |
| 7 #include "skia/ext/image_operations.h" | |
| 8 #include "ui/aura/window.h" | |
| 9 #include "ui/base/resource/resource_bundle.h" | |
| 10 #include "ui/compositor/dip_util.h" | |
| 11 #include "ui/gfx/canvas.h" | |
| 12 #include "ui/gfx/geometry/size_conversions.h" | |
| 13 #include "ui/resources/grit/ui_resources.h" | |
| 14 #include "ui/views/widget/widget.h" | |
| 15 #include "ui/wm/core/shadow_types.h" | |
| 16 | |
| 17 namespace ash { | |
| 18 namespace { | |
| 19 using views::Widget; | |
| 20 | |
| 21 Widget* CreateDragWidget(gfx::NativeView context) { | |
| 22 Widget* drag_widget = new Widget; | |
| 23 Widget::InitParams params; | |
| 24 params.type = Widget::InitParams::TYPE_TOOLTIP; | |
| 25 params.keep_on_top = true; | |
| 26 params.context = context; | |
| 27 params.accept_events = false; | |
| 28 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 29 params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; | |
| 30 drag_widget->Init(params); | |
| 31 drag_widget->SetOpacity(1.f); | |
| 32 drag_widget->GetNativeWindow()->set_owned_by_parent(false); | |
| 33 drag_widget->GetNativeWindow()->SetName("DragWidget"); | |
| 34 SetShadowType(drag_widget->GetNativeView(), wm::SHADOW_TYPE_NONE); | |
| 35 return drag_widget; | |
| 36 } | |
| 37 } | |
| 38 | |
| 39 DragImageView::DragImageView(gfx::NativeView context, | |
| 40 ui::DragDropTypes::DragEventSource event_source) | |
| 41 : views::ImageView(), | |
| 42 drag_event_source_(event_source), | |
| 43 touch_drag_operation_(ui::DragDropTypes::DRAG_NONE) { | |
| 44 widget_.reset(CreateDragWidget(context)); | |
| 45 widget_->SetContentsView(this); | |
| 46 widget_->SetAlwaysOnTop(true); | |
| 47 | |
| 48 // We are owned by the DragDropController. | |
| 49 set_owned_by_client(); | |
| 50 } | |
| 51 | |
| 52 DragImageView::~DragImageView() { | |
| 53 widget_->Hide(); | |
| 54 } | |
| 55 | |
| 56 void DragImageView::SetBoundsInScreen(const gfx::Rect& bounds) { | |
| 57 widget_->SetBounds(bounds); | |
| 58 widget_size_ = bounds.size(); | |
| 59 } | |
| 60 | |
| 61 void DragImageView::SetScreenPosition(const gfx::Point& position) { | |
| 62 widget_->SetBounds(gfx::Rect(position, widget_size_)); | |
| 63 } | |
| 64 | |
| 65 gfx::Rect DragImageView::GetBoundsInScreen() const { | |
| 66 return widget_->GetWindowBoundsInScreen(); | |
| 67 } | |
| 68 | |
| 69 void DragImageView::SetWidgetVisible(bool visible) { | |
| 70 if (visible != widget_->IsVisible()) { | |
| 71 if (visible) | |
| 72 widget_->Show(); | |
| 73 else | |
| 74 widget_->Hide(); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 void DragImageView::SetTouchDragOperationHintOff() { | |
| 79 // Simply set the drag type to non-touch so that no hint is drawn. | |
| 80 drag_event_source_ = ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; | |
| 81 SchedulePaint(); | |
| 82 } | |
| 83 | |
| 84 void DragImageView::SetTouchDragOperation(int operation) { | |
| 85 if (touch_drag_operation_ == operation) | |
| 86 return; | |
| 87 touch_drag_operation_ = operation; | |
| 88 SchedulePaint(); | |
| 89 } | |
| 90 | |
| 91 void DragImageView::SetTouchDragOperationHintPosition( | |
| 92 const gfx::Point& position) { | |
| 93 if (touch_drag_operation_indicator_position_ == position) | |
| 94 return; | |
| 95 touch_drag_operation_indicator_position_ = position; | |
| 96 SchedulePaint(); | |
| 97 } | |
| 98 | |
| 99 void DragImageView::SetOpacity(float visibility) { | |
| 100 DCHECK_GE(visibility, 0.0f); | |
| 101 DCHECK_LE(visibility, 1.0f); | |
| 102 widget_->SetOpacity(visibility); | |
| 103 } | |
| 104 | |
| 105 void DragImageView::OnPaint(gfx::Canvas* canvas) { | |
| 106 if (GetImage().isNull()) | |
| 107 return; | |
| 108 | |
| 109 // |widget_size_| is in DIP. ImageSkia::size() also returns the size in DIP. | |
| 110 if (GetImage().size() == widget_size_) { | |
| 111 canvas->DrawImageInt(GetImage(), 0, 0); | |
| 112 } else { | |
| 113 float device_scale = 1; | |
| 114 if (widget_->GetNativeView() && widget_->GetNativeView()->layer()) { | |
| 115 device_scale = | |
| 116 ui::GetDeviceScaleFactor(widget_->GetNativeView()->layer()); | |
| 117 } | |
| 118 // The drag image already has device scale factor applied. But | |
| 119 // |widget_size_| is in DIP units. | |
| 120 gfx::Size scaled_widget_size = | |
| 121 gfx::ScaleToRoundedSize(widget_size_, device_scale); | |
| 122 gfx::ImageSkiaRep image_rep = GetImage().GetRepresentation(device_scale); | |
| 123 if (image_rep.is_null()) | |
| 124 return; | |
| 125 SkBitmap scaled = skia::ImageOperations::Resize( | |
| 126 image_rep.sk_bitmap(), skia::ImageOperations::RESIZE_LANCZOS3, | |
| 127 scaled_widget_size.width(), scaled_widget_size.height()); | |
| 128 gfx::ImageSkia image_skia(gfx::ImageSkiaRep(scaled, device_scale)); | |
| 129 canvas->DrawImageInt(image_skia, 0, 0); | |
| 130 } | |
| 131 | |
| 132 if (drag_event_source_ != ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) | |
| 133 return; | |
| 134 | |
| 135 gfx::Image* drag_hint = DragHint(); | |
| 136 if (drag_hint->IsEmpty()) | |
| 137 return; | |
| 138 | |
| 139 // Make sure drag hint image is positioned within the widget. | |
| 140 gfx::Size drag_hint_size = drag_hint->Size(); | |
| 141 gfx::Point drag_hint_position = touch_drag_operation_indicator_position_; | |
| 142 drag_hint_position.Offset(-drag_hint_size.width() / 2, 0); | |
| 143 gfx::Rect drag_hint_bounds(drag_hint_position, drag_hint_size); | |
| 144 drag_hint_bounds.AdjustToFit(gfx::Rect(widget_size_)); | |
| 145 | |
| 146 // Draw image. | |
| 147 canvas->DrawImageInt(*(drag_hint->ToImageSkia()), drag_hint_bounds.x(), | |
| 148 drag_hint_bounds.y()); | |
| 149 } | |
| 150 | |
| 151 gfx::Image* DragImageView::DragHint() const { | |
| 152 // Select appropriate drag hint. | |
| 153 gfx::Image* drag_hint = | |
| 154 &ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 155 IDR_TOUCH_DRAG_TIP_NODROP); | |
| 156 if (touch_drag_operation_ & ui::DragDropTypes::DRAG_COPY) { | |
| 157 drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 158 IDR_TOUCH_DRAG_TIP_COPY); | |
| 159 } else if (touch_drag_operation_ & ui::DragDropTypes::DRAG_MOVE) { | |
| 160 drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 161 IDR_TOUCH_DRAG_TIP_MOVE); | |
| 162 } else if (touch_drag_operation_ & ui::DragDropTypes::DRAG_LINK) { | |
| 163 drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
| 164 IDR_TOUCH_DRAG_TIP_LINK); | |
| 165 } | |
| 166 return drag_hint; | |
| 167 } | |
| 168 | |
| 169 void DragImageView::Layout() { | |
| 170 View::Layout(); | |
| 171 | |
| 172 gfx::Image* drag_hint = DragHint(); | |
| 173 if (drag_hint->IsEmpty()) | |
| 174 return; | |
| 175 | |
| 176 gfx::Size drag_hint_size = drag_hint->Size(); | |
| 177 | |
| 178 // Enlarge widget if required to fit the drag hint image. | |
| 179 if (drag_hint_size.width() > widget_size_.width() || | |
| 180 drag_hint_size.height() > widget_size_.height()) { | |
| 181 gfx::Size new_widget_size = widget_size_; | |
| 182 new_widget_size.SetToMax(drag_hint_size); | |
| 183 widget_->SetSize(new_widget_size); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 } // namespace ash | |
| OLD | NEW |