// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Ken VanDine * */ #include "unity-shared/IntrospectableWrappers.h" #include "unity-shared/PreviewStyle.h" #include "unity-shared/CoverArt.h" #include "unity-shared/IconTexture.h" #include #include #include #include #include #include #include "config.h" #include #include "SocialPreview.h" #include "SocialPreviewContent.h" #include "SocialPreviewComments.h" #include "ActionButton.h" #include "PreviewInfoHintWidget.h" namespace unity { namespace dash { namespace previews { DECLARE_LOGGER(logger, "unity.dash.preview.social"); namespace { const RawPixel CHILDREN_SPACE = 16_em; const RawPixel ICON_CHILDREN_SPACE = 3_em; const RawPixel SOCIAL_INFO_CHILDREN_SPACE = 12_em; } NUX_IMPLEMENT_OBJECT_TYPE(SocialPreview); SocialPreview::SocialPreview(dash::Preview::Ptr preview_model) : Preview(preview_model) , image_data_layout_(nullptr) , main_social_info_(nullptr) , comments_layout_(nullptr) , social_content_layout_(nullptr) , social_data_layout_(nullptr) , social_info_layout_(nullptr) , social_info_scroll_(nullptr) , icon_layout_(nullptr) , actions_layout_(nullptr) { SetupViews(); UpdateScale(scale); } SocialPreview::~SocialPreview() { } void SocialPreview::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw) { nux::Geometry const& base = GetGeometry(); gfx_engine.PushClippingRectangle(base); nux::GetPainter().PaintBackground(gfx_engine, base); gfx_engine.PopClippingRectangle(); } void SocialPreview::DrawContent(nux::GraphicsEngine& gfx_engine, bool force_draw) { nux::Geometry const& base = GetGeometry(); gfx_engine.PushClippingRectangle(base); unsigned int alpha, src, dest = 0; gfx_engine.GetRenderStates().GetBlend(alpha, src, dest); gfx_engine.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (GetCompositionLayout()) GetCompositionLayout()->ProcessDraw(gfx_engine, force_draw); gfx_engine.GetRenderStates().SetBlend(alpha, src, dest); gfx_engine.PopClippingRectangle(); } std::string SocialPreview::GetName() const { return "SocialPreview"; } void SocialPreview::AddProperties(debug::IntrospectionData& introspection) { Preview::AddProperties(introspection); } void SocialPreview::SetupViews() { dash::SocialPreview* social_preview_model = dynamic_cast(preview_model_.get()); if (!social_preview_model) { LOG_ERROR(logger) << "Could not derive social preview model from given parameter."; return; } previews::Style& style = dash::previews::Style::Instance(); auto on_mouse_down = [this](int x, int y, unsigned long button_flags, unsigned long key_flags) { this->preview_container_->OnMouseDown(x, y, button_flags, key_flags); }; image_data_layout_ = new nux::HLayout(); image_data_layout_->SetSpaceBetweenChildren(style.GetPanelSplitWidth().CP(scale)); nux::VLayout* social_content_layout_ = new nux::VLayout(); social_content_layout_->SetSpaceBetweenChildren(CHILDREN_SPACE.CP(scale)); if (social_preview_model->description.Get().length() > 0) { content_ = new SocialPreviewContent(social_preview_model->description, NUX_TRACKER_LOCATION); content_->request_close().connect([this]() { preview_container_->request_close.emit(); }); social_content_layout_->AddView(content_.GetPointer(), 1); } else { image_ = new CoverArt(); AddChild(image_.GetPointer()); UpdateCoverArtImage(image_.GetPointer()); social_content_layout_->AddView(image_.GetPointer(), 1); } ///////////////////// ///////////////////// // Social Data Panel full_data_layout_ = new nux::VLayout(); full_data_layout_->SetPadding(style.GetDetailsTopMargin().CP(scale), 0, style.GetDetailsBottomMargin().CP(scale), style.GetDetailsLeftMargin().CP(scale)); full_data_layout_->SetSpaceBetweenChildren(CHILDREN_SPACE.CP(scale)); ///////////////////// // Main Social Info main_social_info_ = new nux::HLayout(); main_social_info_->SetSpaceBetweenChildren(style.GetSpaceBetweenIconAndDetails().CP(scale)); ///////////////////// // Icon Layout icon_layout_ = new nux::VLayout(); icon_layout_->SetSpaceBetweenChildren(ICON_CHILDREN_SPACE.CP(scale)); avatar_ = new IconTexture(social_preview_model->avatar() ? g_icon_to_string(social_preview_model->avatar()) : "", MIN(style.GetAvatarAreaWidth().CP(scale), style.GetAvatarAreaHeight().CP(scale))); AddChild(avatar_.GetPointer()); avatar_->SetMinMaxSize(style.GetAvatarAreaWidth().CP(scale), style.GetAvatarAreaHeight().CP(scale)); avatar_->mouse_click.connect(on_mouse_down); icon_layout_->AddView(avatar_.GetPointer(), 0); ///////////////////// ///////////////////// // Data social_data_layout_ = new nux::VLayout(); social_data_layout_->SetSpaceBetweenChildren(style.GetSpaceBetweenTitleAndSubtitle().CP(scale)); title_ = new StaticCairoText(preview_model_->title, true, NUX_TRACKER_LOCATION); AddChild(title_.GetPointer()); title_->SetLines(-1); title_->SetScale(scale); title_->SetFont(style.title_font().c_str()); title_->mouse_click.connect(on_mouse_down); subtitle_ = new StaticCairoText(preview_model_->subtitle, true, NUX_TRACKER_LOCATION); AddChild(subtitle_.GetPointer()); subtitle_->SetFont(style.content_font().c_str()); subtitle_->SetLines(-1); subtitle_->SetScale(scale); subtitle_->mouse_click.connect(on_mouse_down); social_data_layout_->AddView(title_.GetPointer(), 0); social_data_layout_->AddView(subtitle_.GetPointer(), 0); social_data_layout_->AddSpace(0, 1); // buffer space ///////////////////// main_social_info_->AddLayout(icon_layout_, 0); main_social_info_->AddLayout(social_data_layout_, 1); ///////////////////// ///////////////////// // Details auto* social_info = new ScrollView(NUX_TRACKER_LOCATION); social_info_scroll_ = social_info; social_info->scale = scale(); social_info->EnableHorizontalScrollBar(false); social_info->mouse_click.connect(on_mouse_down); social_info_layout_ = new nux::VLayout(); social_info_layout_->SetSpaceBetweenChildren(SOCIAL_INFO_CHILDREN_SPACE.CP(scale)); social_info->SetLayout(social_info_layout_); if (!preview_model_->GetInfoHints().empty()) { preview_info_hints_ = new PreviewInfoHintWidget(preview_model_, style.GetAvatarAreaWidth()); AddChild(preview_info_hints_.GetPointer()); preview_info_hints_->request_close().connect([this]() { preview_container_->request_close.emit(); }); social_info_layout_->AddView(preview_info_hints_.GetPointer(), 0); } ///////////////////// // Comments/Replies if (!social_preview_model->GetComments().empty()) { comments_layout_ = new nux::HLayout(); comments_layout_->SetSpaceBetweenChildren(SOCIAL_INFO_CHILDREN_SPACE.CP(scale)); std::string tmp_comments_hint = _("Comments"); tmp_comments_hint += ":"; comments_hint_ = new StaticCairoText(tmp_comments_hint, true, NUX_TRACKER_LOCATION); AddChild(comments_hint_.GetPointer()); comments_hint_->SetLines(-1); comments_hint_->SetScale(scale); comments_hint_->SetFont(style.info_hint_bold_font().c_str()); comments_hint_->SetTextAlignment(StaticCairoText::NUX_ALIGN_RIGHT); comments_hint_->mouse_click.connect(on_mouse_down); comments_layout_->AddView(comments_hint_.GetPointer(), 0, nux::MINOR_POSITION_START); comments_ = new SocialPreviewComments(preview_model_, NUX_TRACKER_LOCATION); AddChild(comments_.GetPointer()); comments_->request_close().connect([this]() { preview_container_->request_close.emit(); }); comments_layout_->AddView(comments_.GetPointer()); social_info_layout_->AddView(comments_layout_, 0); } ///////////////////// // Actions action_buttons_.clear(); actions_layout_ = BuildGridActionsLayout(preview_model_->GetActions(), action_buttons_); actions_layout_->SetLeftAndRightPadding(0, style.GetDetailsRightMargin().CP(scale)); /////////////////// full_data_layout_->AddLayout(main_social_info_, 0, nux::MINOR_POSITION_START); full_data_layout_->AddView(social_info, 1, nux::MINOR_POSITION_START); //full_data_layout_->AddView(comments_.GetPointer(), 1, nux::MINOR_POSITION_START); full_data_layout_->AddLayout(actions_layout_, 0); ///////////////////// image_data_layout_->AddView(social_content_layout_, 0); image_data_layout_->AddLayout(full_data_layout_, 1); mouse_click.connect(on_mouse_down); SetLayout(image_data_layout_); } void SocialPreview::PreLayoutManagement() { nux::Geometry geo = GetGeometry(); previews::Style& style = dash::previews::Style::Instance(); nux::Geometry geo_content(geo.x, geo.y, style.GetAppImageAspectRatio() * geo.height, geo.height); int content_width = geo.width - style.GetPanelSplitWidth().CP(scale) - style.GetDetailsLeftMargin().CP(scale) - style.GetDetailsRightMargin().CP(scale); if (content_width - geo_content.width < style.GetDetailsPanelMinimumWidth().CP(scale)) geo_content.width = std::max(0, content_width - style.GetDetailsPanelMinimumWidth().CP(scale)); if (content_) { content_->SetMinMaxSize(geo_content.width, geo_content.height); } if (image_) { image_->SetMinMaxSize(geo_content.width, geo_content.height); } int details_width = std::max(0, content_width - geo_content.width); int top_social_info_max_width = std::max(0, details_width - style.GetAppIconAreaWidth().CP(scale) - style.GetSpaceBetweenIconAndDetails().CP(scale)); if (title_) { title_->SetMaximumWidth(top_social_info_max_width); } if (subtitle_) { subtitle_->SetMaximumWidth(top_social_info_max_width); } if (comments_) { comments_->SetMaximumWidth(top_social_info_max_width); } if (comments_hint_) { comments_hint_->SetMinimumWidth(style.GetInfoHintNameMinimumWidth().CP(scale)); } int button_w = CLAMP((details_width - style.GetSpaceBetweenActions().CP(scale)) / 2, 0, style.GetActionButtonMaximumWidth().CP(scale)); int button_h = style.GetActionButtonHeight().CP(scale); for (nux::AbstractButton* button : action_buttons_) button->SetMinMaxSize(button_w, button_h); Preview::PreLayoutManagement(); } void SocialPreview::UpdateScale(double scale) { Preview::UpdateScale(scale); if (preview_info_hints_) preview_info_hints_->scale = scale; previews::Style& style = dash::previews::Style::Instance(); if (avatar_) { avatar_->SetMinMaxSize(style.GetAvatarAreaWidth().CP(scale), style.GetAvatarAreaHeight().CP(scale)); avatar_->SetSize(MIN(style.GetAvatarAreaWidth().CP(scale), style.GetAvatarAreaHeight().CP(scale))); avatar_->ReLoadIcon(); } if (image_data_layout_) image_data_layout_->SetSpaceBetweenChildren(style.GetPanelSplitWidth().CP(scale)); if (social_content_layout_) social_content_layout_->SetSpaceBetweenChildren(CHILDREN_SPACE.CP(scale)); if (main_social_info_) main_social_info_->SetSpaceBetweenChildren(style.GetSpaceBetweenIconAndDetails().CP(scale)); if (icon_layout_) icon_layout_->SetSpaceBetweenChildren(ICON_CHILDREN_SPACE.CP(scale)); if (social_data_layout_) social_data_layout_->SetSpaceBetweenChildren(style.GetSpaceBetweenTitleAndSubtitle().CP(scale)); if (social_info_layout_) social_info_layout_->SetSpaceBetweenChildren(SOCIAL_INFO_CHILDREN_SPACE.CP(scale)); if (social_info_scroll_) social_info_scroll_->scale = scale; if (actions_layout_) actions_layout_->SetLeftAndRightPadding(0, style.GetDetailsRightMargin().CP(scale)); if (content_) content_->scale = scale; if (comments_) comments_->scale = scale; if (comments_layout_) comments_layout_->SetSpaceBetweenChildren(SOCIAL_INFO_CHILDREN_SPACE.CP(scale)); if (comments_hint_) comments_hint_->SetScale(scale); } } // namespace previews } // namespace dash } // namepsace unity