forked from organicmaps/organicmaps
[core] new download buttons from map view
This commit is contained in:
parent
b0a390f194
commit
e931bb1600
9 changed files with 471 additions and 307 deletions
|
@ -110,7 +110,7 @@ namespace graphics
|
|||
return m_flags[VISIBLE];
|
||||
}
|
||||
|
||||
void OverlayElement::setIsVisible(bool flag)
|
||||
void OverlayElement::setIsVisible(bool flag) const
|
||||
{
|
||||
m_flags[VISIBLE] = flag;
|
||||
}
|
||||
|
|
|
@ -108,10 +108,10 @@ namespace graphics
|
|||
void setIsNeedRedraw(bool flag);
|
||||
|
||||
bool isDirtyLayout() const;
|
||||
void setIsDirtyLayout(bool flag) const;
|
||||
virtual void setIsDirtyLayout(bool flag) const;
|
||||
|
||||
virtual bool isVisible() const;
|
||||
virtual void setIsVisible(bool flag);
|
||||
virtual void setIsVisible(bool flag) const;
|
||||
|
||||
bool isValid() const;
|
||||
void setIsValid(bool flag);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "button.hpp"
|
||||
#include "controller.hpp"
|
||||
#include "text_view.hpp"
|
||||
|
||||
#include "../graphics/screen.hpp"
|
||||
#include "../graphics/display_list.hpp"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "element.hpp"
|
||||
#include "text_view.hpp"
|
||||
|
||||
#include "../std/function.hpp"
|
||||
#include "../std/string.hpp"
|
||||
|
@ -20,8 +21,6 @@ namespace graphics
|
|||
|
||||
namespace gui
|
||||
{
|
||||
class TextView;
|
||||
|
||||
class Button : public Element
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../../graphics/display_list.hpp"
|
||||
|
||||
#include "../../map/country_status_display.hpp"
|
||||
#include "../../map/framework.hpp"
|
||||
|
||||
|
||||
struct ButtonTest
|
||||
|
@ -129,24 +130,23 @@ struct ImageViewTest
|
|||
struct CountryStatusDisplayTest
|
||||
{
|
||||
shared_ptr<CountryStatusDisplay> m_countryStatus;
|
||||
shared_ptr<storage::Storage> m_storage;
|
||||
shared_ptr<Framework> m_framework;
|
||||
m2::PointD m_pivot;
|
||||
|
||||
void Init(gui::Controller * c)
|
||||
{
|
||||
CountryStatusDisplay::Params p;
|
||||
CountryStatusDisplay::Params p(m_framework->GetCountryTree().GetActiveMapLayout());
|
||||
|
||||
m_pivot = m2::PointD(400, 400);
|
||||
|
||||
m_storage.reset(new storage::Storage());
|
||||
m_framework.reset(new Framework());
|
||||
|
||||
p.m_depth = graphics::maxDepth;
|
||||
p.m_pivot = m_pivot;
|
||||
p.m_position = graphics::EPosAboveLeft;
|
||||
p.m_storage = m_storage.get();
|
||||
|
||||
m_countryStatus.reset(new CountryStatusDisplay(p));
|
||||
m_countryStatus->setCountryIndex(storage::TIndex(1, 1, 1));
|
||||
m_countryStatus->SetCountryIndex(storage::TIndex(1, 1, 1));
|
||||
m_countryStatus->setPivot(m_pivot);
|
||||
c->AddElement(m_countryStatus);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
#include "country_status_display.hpp"
|
||||
#include "framework.hpp"
|
||||
|
||||
#include "../gui/controller.hpp"
|
||||
#include "../gui/button.hpp"
|
||||
#include "../gui/text_view.hpp"
|
||||
|
||||
#include "../graphics/overlay_renderer.hpp"
|
||||
#include "../graphics/display_list.hpp"
|
||||
|
||||
#include "../storage/storage_defines.hpp"
|
||||
#include "../platform/platform.hpp"
|
||||
|
||||
#include "../base/thread.hpp"
|
||||
|
||||
#include "../base/string_format.hpp"
|
||||
|
||||
#include "../std/bind.hpp"
|
||||
|
@ -16,21 +19,224 @@
|
|||
|
||||
using namespace storage;
|
||||
|
||||
CountryStatusDisplay::Params::Params()
|
||||
: m_storage(0)
|
||||
CountryStatusDisplay::CountryStatusDisplay(Params const & p)
|
||||
: gui::Element(p)
|
||||
, m_activeMaps(p.m_activeMaps)
|
||||
{
|
||||
m_activeMapsSlotID = m_activeMaps.AddListener(this);
|
||||
gui::Button::Params bp;
|
||||
|
||||
bp.m_depth = depth();
|
||||
bp.m_minWidth = 200;
|
||||
bp.m_minHeight = 40;
|
||||
bp.m_position = graphics::EPosCenter;
|
||||
|
||||
auto createButtonFn = [this](gui::Button::Params const & params)
|
||||
{
|
||||
gui::Button * result = new gui::Button(params);
|
||||
result->setIsVisible(false);
|
||||
result->setOnClickListener(bind(&CountryStatusDisplay::OnButtonClicked, this, _1));
|
||||
|
||||
result->setFont(EActive, graphics::FontDesc(16, graphics::Color(255, 255, 255, 255)));
|
||||
result->setFont(EPressed, graphics::FontDesc(16, graphics::Color(255, 255, 255, 255)));
|
||||
|
||||
result->setColor(EActive, graphics::Color(0, 0, 0, 0.6 * 255));
|
||||
result->setColor(EPressed, graphics::Color(0, 0, 0, 0.4 * 255));
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
m_primaryButton.reset(createButtonFn(bp));
|
||||
m_secondaryButton.reset(createButtonFn(bp));
|
||||
|
||||
gui::TextView::Params tp;
|
||||
tp.m_depth = depth();
|
||||
tp.m_position = graphics::EPosCenter;
|
||||
|
||||
m_label.reset(new gui::TextView(tp));
|
||||
m_label->setIsVisible(false);
|
||||
m_label->setFont(gui::Element::EActive, graphics::FontDesc(18));
|
||||
|
||||
setIsVisible(false);
|
||||
}
|
||||
|
||||
string const CountryStatusDisplay::displayName() const
|
||||
CountryStatusDisplay::~CountryStatusDisplay()
|
||||
{
|
||||
if (!m_mapGroupName.empty())
|
||||
return m_mapName + " (" + m_mapGroupName + ")";
|
||||
else
|
||||
return m_mapName;
|
||||
m_activeMaps.RemoveListener(m_activeMapsSlotID);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::SetCountryIndex(TIndex const & idx)
|
||||
{
|
||||
if (m_countryIdx != idx)
|
||||
{
|
||||
m_countryIdx = idx;
|
||||
|
||||
if (m_countryIdx.IsValid())
|
||||
{
|
||||
m_countryStatus = m_activeMaps.GetCountryStatus(m_countryIdx);
|
||||
m_displayMapName = m_activeMaps.GetFormatedCountryName(m_countryIdx);
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::DownloadCurrentCountry(int options)
|
||||
{
|
||||
// I don't know why this work, but it's terrible
|
||||
// This method call only on android, from "AndroidUIThread"
|
||||
DownloadCountry(options, false);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setIsVisible(bool isVisible) const
|
||||
{
|
||||
if (isVisible && isVisible != TBase::isVisible())
|
||||
Repaint();
|
||||
|
||||
TBase::setIsVisible(isVisible);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setIsDirtyLayout(bool isDirty) const
|
||||
{
|
||||
TBase::setIsDirtyLayout(isDirty);
|
||||
m_label->setIsDirtyLayout(isDirty);
|
||||
m_primaryButton->setIsDirtyLayout(isDirty);
|
||||
m_secondaryButton->setIsDirtyLayout(isDirty);
|
||||
|
||||
if (isDirty)
|
||||
SetVisibilityForState();
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::draw(graphics::OverlayRenderer * r,
|
||||
math::Matrix<double, 3, 3> const & m) const
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
Lock();
|
||||
checkDirtyLayout();
|
||||
|
||||
m_label->draw(r, m);
|
||||
m_primaryButton->draw(r, m);
|
||||
m_secondaryButton->draw(r, m);
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::layout()
|
||||
{
|
||||
if (!isVisible())
|
||||
return;
|
||||
SetContentForState();
|
||||
|
||||
auto layoutFn = [] (gui::Element * e)
|
||||
{
|
||||
if (e->isVisible())
|
||||
e->layout();
|
||||
};
|
||||
|
||||
layoutFn(m_label.get());
|
||||
layoutFn(m_primaryButton.get());
|
||||
layoutFn(m_secondaryButton.get());
|
||||
|
||||
ComposeElementsForState();
|
||||
|
||||
// !!!! Hack !!!!
|
||||
// ComposeElementsForState modify pivot point of elements.
|
||||
// After setPivot all elements must be relayouted.
|
||||
// For reduce "cache" operations we call layout secondary
|
||||
layoutFn(m_label.get());
|
||||
layoutFn(m_primaryButton.get());
|
||||
layoutFn(m_secondaryButton.get());
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::purge()
|
||||
{
|
||||
m_label->purge();
|
||||
m_primaryButton->purge();
|
||||
m_secondaryButton->purge();
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::cache()
|
||||
{
|
||||
auto cacheFn = [](gui::Element * e)
|
||||
{
|
||||
if (e->isVisible())
|
||||
e->cache();
|
||||
};
|
||||
|
||||
cacheFn(m_label.get());
|
||||
cacheFn(m_primaryButton.get());
|
||||
cacheFn(m_secondaryButton.get());
|
||||
}
|
||||
|
||||
m2::RectD CountryStatusDisplay::GetBoundRect() const
|
||||
{
|
||||
ASSERT(isVisible(), ());
|
||||
m2::RectD r(pivot(), pivot());
|
||||
|
||||
if (m_primaryButton->isVisible())
|
||||
r.Add(m_primaryButton->GetBoundRect());
|
||||
if (m_secondaryButton->isVisible())
|
||||
r.Add(m_secondaryButton->GetBoundRect());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setController(gui::Controller * controller)
|
||||
{
|
||||
Element::setController(controller);
|
||||
m_label->setController(controller);
|
||||
m_primaryButton->setController(controller);
|
||||
m_secondaryButton->setController(controller);
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapStarted(m2::PointD const & pt)
|
||||
{
|
||||
return OnTapAction(bind(&gui::Button::onTapStarted, _1, _2), pt);
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapMoved(m2::PointD const & pt)
|
||||
{
|
||||
return OnTapAction(bind(&gui::Button::onTapMoved, _1, _2), pt);
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapEnded(m2::PointD const & pt)
|
||||
{
|
||||
return OnTapAction(bind(&gui::Button::onTapEnded, _1, _2), pt);
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapCancelled(m2::PointD const & pt)
|
||||
{
|
||||
return OnTapAction(bind(&gui::Button::onTapCancelled, _1, _2), pt);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::CountryStatusChanged(ActiveMapsLayout::TGroup const & group, int position)
|
||||
{
|
||||
TIndex index = m_activeMaps.GetCoreIndex(group, position);
|
||||
if (m_countryIdx == index)
|
||||
{
|
||||
Lock();
|
||||
m_countryStatus = m_activeMaps.GetCountryStatus(index);
|
||||
Repaint();
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::DownloadingProgressUpdate(ActiveMapsLayout::TGroup const & group, int position, LocalAndRemoteSizeT const & progress)
|
||||
{
|
||||
TIndex index = m_activeMaps.GetCoreIndex(group, position);
|
||||
if (m_countryIdx == index)
|
||||
{
|
||||
Lock();
|
||||
m_countryStatus = m_activeMaps.GetCountryStatus(index);
|
||||
m_progressSize = progress;
|
||||
Repaint();
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
void CountryStatusDisplay::SetStatusMessage(string const & msgID, T1 const * t1, T2 const * t2)
|
||||
string CountryStatusDisplay::FormatStatusMessage(string const & msgID, T1 const * t1, T2 const * t2)
|
||||
{
|
||||
string msg = m_controller->GetStringsBundle()->GetString(msgID);
|
||||
if (t1)
|
||||
|
@ -50,279 +256,219 @@ void CountryStatusDisplay::SetStatusMessage(string const & msgID, T1 const * t1,
|
|||
}
|
||||
}
|
||||
|
||||
m_statusMsg->setIsVisible(true);
|
||||
m_statusMsg->setText(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::layout()
|
||||
void CountryStatusDisplay::SetVisibilityForState() const
|
||||
{
|
||||
m_downloadButton->setIsDirtyLayout(true);
|
||||
m_statusMsg->setIsDirtyLayout(true);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::purge()
|
||||
{
|
||||
m_downloadButton->purge();
|
||||
m_statusMsg->purge();
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::cache()
|
||||
{
|
||||
m_downloadButton->setIsVisible(false);
|
||||
m_statusMsg->setIsVisible(false);
|
||||
setIsVisible(false);
|
||||
|
||||
string const dn = displayName();
|
||||
uint8_t visibilityFlags = 0;
|
||||
uint8_t const labelVisibility = 0x1;
|
||||
uint8_t const primeVisibility = 0x2;
|
||||
uint8_t const secondaryVisibility = 0x4;
|
||||
|
||||
if (m_countryIdx.IsValid())
|
||||
{
|
||||
switch (m_countryStatus)
|
||||
{
|
||||
case TStatus::EInQueue:
|
||||
{
|
||||
SetStatusMessage<string, int>("country_status_added_to_queue", &dn);
|
||||
break;
|
||||
}
|
||||
|
||||
case TStatus::EDownloading:
|
||||
{
|
||||
int const percent = m_countryProgress.first * 100 / m_countryProgress.second;
|
||||
SetStatusMessage<string, int>("country_status_downloading", &dn, &percent);
|
||||
break;
|
||||
}
|
||||
|
||||
case TStatus::ENotDownloaded:
|
||||
if (m_notEnoughSpace)
|
||||
SetStatusMessage<int, int>("not_enough_free_space_on_sdcard");
|
||||
else
|
||||
{
|
||||
m_downloadButton->setIsVisible(true);
|
||||
string const msg = m_controller->GetStringsBundle()->GetString("country_status_download");
|
||||
m_downloadButton->setText(strings::Format(msg, dn));
|
||||
}
|
||||
break;
|
||||
|
||||
case TStatus::EDownloadFailed:
|
||||
{
|
||||
m_downloadButton->setIsVisible(true);
|
||||
m_downloadButton->setText(m_controller->GetStringsBundle()->GetString("try_again"));
|
||||
SetStatusMessage<string, int>("country_status_download_failed", &dn);
|
||||
|
||||
setPivot(pivot());
|
||||
visibilityFlags |= labelVisibility;
|
||||
visibilityFlags |= primeVisibility;
|
||||
break;
|
||||
case TStatus::EDownloading:
|
||||
case TStatus::EInQueue:
|
||||
visibilityFlags |= labelVisibility;
|
||||
break;
|
||||
case TStatus::ENotDownloaded:
|
||||
visibilityFlags |= labelVisibility;
|
||||
visibilityFlags |= primeVisibility;
|
||||
visibilityFlags |= secondaryVisibility;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setIsVisible(m_statusMsg->isVisible() || m_downloadButton->isVisible());
|
||||
m_label->setIsVisible(visibilityFlags & labelVisibility);
|
||||
m_primaryButton->setIsVisible(visibilityFlags & primeVisibility);
|
||||
m_secondaryButton->setIsVisible(visibilityFlags & secondaryVisibility);
|
||||
|
||||
TBase::setIsVisible(m_label->isVisible() || m_primaryButton->isVisible() || m_secondaryButton->isVisible());
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::CountryStatusChanged(TIndex const & idx)
|
||||
void CountryStatusDisplay::SetContentForState()
|
||||
{
|
||||
if (idx == m_countryIdx)
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
switch (m_countryStatus)
|
||||
{
|
||||
UpdateStatusAndProgress();
|
||||
|
||||
setIsDirtyLayout(true);
|
||||
invalidate();
|
||||
case TStatus::EDownloadFailed:
|
||||
case TStatus::EOutOfMemFailed:
|
||||
SetContentForError();
|
||||
break;
|
||||
case TStatus::ENotDownloaded:
|
||||
SetContentForDownloadPropose();
|
||||
break;
|
||||
case TStatus::EDownloading:
|
||||
SetContentForProgress();
|
||||
break;
|
||||
case TStatus::EInQueue:
|
||||
SetContentForInQueue();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::CountryProgress(TIndex const & idx, pair<int64_t, int64_t> const & progress)
|
||||
void CountryStatusDisplay::SetContentForDownloadPropose()
|
||||
{
|
||||
if ((m_countryIdx == idx) && (m_countryStatus == TStatus::EDownloading))
|
||||
{
|
||||
m_countryProgress = progress;
|
||||
ASSERT(m_label->isVisible(), ());
|
||||
ASSERT(m_primaryButton->isVisible(), ());
|
||||
ASSERT(m_secondaryButton->isVisible(), ());
|
||||
|
||||
setIsDirtyLayout(true);
|
||||
invalidate();
|
||||
}
|
||||
LocalAndRemoteSizeT mapOnlySize = m_activeMaps.GetCountrySize(m_countryIdx, TMapOptions::EMapOnly);
|
||||
LocalAndRemoteSizeT withRouting = m_activeMaps.GetCountrySize(m_countryIdx, TMapOptions::EMapWithCarRouting);
|
||||
|
||||
m_label->setText(m_displayMapName);
|
||||
int mbToDownload = mapOnlySize.second / (1024 * 1024);
|
||||
m_primaryButton->setText(FormatStatusMessage<int, int>("country_status_download", &mbToDownload));
|
||||
mbToDownload = withRouting.second / (1024 * 1024);
|
||||
m_secondaryButton->setText(FormatStatusMessage<int, int>("country_status_download_routing", &mbToDownload));
|
||||
}
|
||||
|
||||
CountryStatusDisplay::CountryStatusDisplay(Params const & p)
|
||||
: gui::Element(p), m_storage(p.m_storage)
|
||||
void CountryStatusDisplay::SetContentForProgress()
|
||||
{
|
||||
m_slotID = m_storage->Subscribe(bind(&CountryStatusDisplay::CountryStatusChanged, this, _1),
|
||||
bind(&CountryStatusDisplay::CountryProgress, this, _1, _2));
|
||||
|
||||
using namespace graphics;
|
||||
|
||||
gui::Button::Params bp;
|
||||
|
||||
bp.m_depth = depth();
|
||||
bp.m_minWidth = 200;
|
||||
bp.m_minHeight = 40;
|
||||
bp.m_position = EPosCenter;
|
||||
|
||||
m_downloadButton.reset(new gui::Button(bp));
|
||||
m_downloadButton->setOnClickListener(bind(&CountryStatusDisplay::downloadCountry, this));
|
||||
m_downloadButton->setIsVisible(false);
|
||||
m_downloadButton->setPosition(EPosCenter);
|
||||
|
||||
m_downloadButton->setFont(EActive, FontDesc(16, Color(255, 255, 255, 255)));
|
||||
m_downloadButton->setFont(EPressed, FontDesc(16, Color(255, 255, 255, 255)));
|
||||
|
||||
m_downloadButton->setColor(EActive, Color(Color(0, 0, 0, 0.6 * 255)));
|
||||
m_downloadButton->setColor(EPressed, Color(Color(0, 0, 0, 0.4 * 255)));
|
||||
|
||||
gui::TextView::Params tp;
|
||||
tp.m_depth = depth();
|
||||
|
||||
m_statusMsg.reset(new gui::TextView(tp));
|
||||
|
||||
m_statusMsg->setIsVisible(false);
|
||||
m_statusMsg->setPosition(EPosCenter);
|
||||
|
||||
m_statusMsg->setFont(gui::Element::EActive, FontDesc(18));
|
||||
|
||||
setIsVisible(false);
|
||||
|
||||
m_countryIdx = TIndex();
|
||||
m_countryStatus = TStatus::EUnknown;
|
||||
m_notEnoughSpace = false;
|
||||
ASSERT(m_label->isVisible(), ());
|
||||
int const percent = m_progressSize.first * 100 / m_progressSize.second;
|
||||
m_label->setText(FormatStatusMessage<string, int>("country_status_downloading", &m_displayMapName, &percent));
|
||||
}
|
||||
|
||||
CountryStatusDisplay::~CountryStatusDisplay()
|
||||
void CountryStatusDisplay::SetContentForInQueue()
|
||||
{
|
||||
m_storage->Unsubscribe(m_slotID);
|
||||
ASSERT(m_label->isVisible(), ());
|
||||
m_label->setText(FormatStatusMessage<string, int>("country_status_added_to_queue", &m_displayMapName));
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::downloadCountry()
|
||||
void CountryStatusDisplay::SetContentForError()
|
||||
{
|
||||
if (GetPlatform().GetWritableStorageStatus(m_countryProgress.second) != Platform::STORAGE_OK)
|
||||
{
|
||||
m_notEnoughSpace = true;
|
||||
ASSERT(m_label->isVisible(), ());
|
||||
ASSERT(m_primaryButton->isVisible(), ());
|
||||
|
||||
setIsDirtyLayout(true);
|
||||
invalidate();
|
||||
}
|
||||
else
|
||||
m_storage->DownloadCountry(m_countryIdx, storage::TMapOptions::EMapOnly);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setDownloadListener(gui::Button::TOnClickListener const & l)
|
||||
{
|
||||
m_downloadButton->setOnClickListener(l);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::UpdateStatusAndProgress()
|
||||
{
|
||||
// Actually right now actual status is getting from Framework.
|
||||
// But here it's enough to get it from Storage because of we need only
|
||||
// download progress statuses.
|
||||
|
||||
using namespace storage;
|
||||
|
||||
m_countryProgress = m_storage->CountrySizeInBytes(m_countryIdx);
|
||||
|
||||
m_countryStatus = m_storage->CountryStatus(m_countryIdx);
|
||||
if (m_countryStatus == TStatus::EUnknown)
|
||||
{
|
||||
if (m_countryProgress.first > 0)
|
||||
m_countryStatus = TStatus::EOnDisk;
|
||||
else
|
||||
m_countryStatus = TStatus::ENotDownloaded;
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setCountryIndex(TIndex const & idx)
|
||||
{
|
||||
if (m_countryIdx != idx)
|
||||
{
|
||||
m_countryIdx = idx;
|
||||
|
||||
if (m_countryIdx.IsValid())
|
||||
{
|
||||
m_storage->GetGroupAndCountry(idx, m_mapGroupName, m_mapName);
|
||||
LOG(LDEBUG, (m_mapName, m_mapGroupName));
|
||||
|
||||
UpdateStatusAndProgress();
|
||||
|
||||
m_notEnoughSpace = false;
|
||||
}
|
||||
|
||||
setIsDirtyLayout(true);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::draw(graphics::OverlayRenderer *r,
|
||||
math::Matrix<double, 3, 3> const & m) const
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
checkDirtyLayout();
|
||||
|
||||
if (m_downloadButton->isVisible())
|
||||
m_downloadButton->draw(r, m);
|
||||
if (m_statusMsg->isVisible())
|
||||
m_statusMsg->draw(r, m);
|
||||
}
|
||||
}
|
||||
|
||||
m2::RectD CountryStatusDisplay::GetBoundRect() const
|
||||
{
|
||||
m2::RectD r(pivot(), pivot());
|
||||
if (m_downloadButton->isVisible())
|
||||
r.Add(m_downloadButton->GetBoundRect());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setController(gui::Controller * controller)
|
||||
{
|
||||
Element::setController(controller);
|
||||
m_statusMsg->setController(controller);
|
||||
m_downloadButton->setController(controller);
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::setPivot(m2::PointD const & pv)
|
||||
{
|
||||
if (m_countryStatus == TStatus::EDownloadFailed)
|
||||
{
|
||||
size_t const buttonHeight = m_downloadButton->GetBoundRect().SizeY();
|
||||
size_t const statusHeight = m_statusMsg->GetBoundRect().SizeY();
|
||||
size_t const commonHeight = buttonHeight + statusHeight + 10 * visualScale();
|
||||
m_label->setText(FormatStatusMessage<string, int>("country_status_download_failed", &m_displayMapName));
|
||||
else
|
||||
m_label->setText(FormatStatusMessage<int, int>("not_enough_free_space_on_sdcard"));
|
||||
|
||||
m_downloadButton->setPivot(m2::PointD(pv.x, pv.y + commonHeight / 2 - buttonHeight / 2));
|
||||
m_statusMsg->setPivot(m2::PointD(pv.x, pv.y - commonHeight / 2 + statusHeight / 2));
|
||||
m_primaryButton->setText(m_controller->GetStringsBundle()->GetString("try_again"));
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::ComposeElementsForState()
|
||||
{
|
||||
ASSERT(isVisible(), ());
|
||||
int visibleCount = 0;
|
||||
auto visibleCheckFn = [&visibleCount](gui::Element const * e)
|
||||
{
|
||||
if (e->isVisible())
|
||||
++visibleCount;
|
||||
};
|
||||
|
||||
visibleCheckFn(m_label.get());
|
||||
visibleCheckFn(m_primaryButton.get());
|
||||
visibleCheckFn(m_secondaryButton.get());
|
||||
|
||||
ASSERT(visibleCount > 0, ());
|
||||
|
||||
m2::PointD const & pv = pivot();
|
||||
if (visibleCount == 1)
|
||||
m_label->setPivot(pv);
|
||||
else if (visibleCount == 2)
|
||||
{
|
||||
size_t const labelHeight = m_label->GetBoundRect().SizeY();
|
||||
size_t const buttonHeight = m_primaryButton->GetBoundRect().SizeY();
|
||||
size_t const commonHeight = buttonHeight + labelHeight + 10 * visualScale();
|
||||
|
||||
m_label->setPivot(m2::PointD(pv.x, pv.y - commonHeight / 2 + labelHeight / 2));
|
||||
m_primaryButton->setPivot(m2::PointD(pv.x, pv.y + commonHeight / 2 - buttonHeight / 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_downloadButton->setPivot(pv);
|
||||
m_statusMsg->setPivot(pv);
|
||||
size_t const labelHeight = m_label->GetBoundRect().SizeY();
|
||||
size_t const primButtonHeight = m_primaryButton->GetBoundRect().SizeY();
|
||||
size_t const secButtonHeight = m_secondaryButton->GetBoundRect().SizeY();
|
||||
size_t const emptySpace = 10 * visualScale();
|
||||
|
||||
double const offsetFromCenter = (primButtonHeight / 2 + emptySpace);
|
||||
|
||||
m_label->setPivot(m2::PointD(pv.x, pv.y - offsetFromCenter - labelHeight / 2));
|
||||
m_primaryButton->setPivot(pv);
|
||||
m_secondaryButton->setPivot(m2::PointD(pv.x, pv.y + offsetFromCenter + secButtonHeight / 2.0));
|
||||
}
|
||||
|
||||
gui::Element::setPivot(pv);
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapStarted(m2::PointD const & pt)
|
||||
bool CountryStatusDisplay::OnTapAction(TTapActionFn const & action, const m2::PointD & pt)
|
||||
{
|
||||
if (m_downloadButton->isVisible())
|
||||
return m_downloadButton->onTapStarted(pt);
|
||||
return false;
|
||||
bool result = false;
|
||||
if (m_primaryButton->isVisible() && m_primaryButton->hitTest(pt))
|
||||
result |= action(m_primaryButton, pt);
|
||||
else if (m_secondaryButton->isVisible() && m_secondaryButton->hitTest(pt))
|
||||
result |= action(m_secondaryButton, pt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapMoved(m2::PointD const & pt)
|
||||
void CountryStatusDisplay::OnButtonClicked(gui::Element const * button)
|
||||
{
|
||||
if (m_downloadButton->isVisible())
|
||||
return m_downloadButton->onTapMoved(pt);
|
||||
return false;
|
||||
ASSERT(m_countryIdx.IsValid(), ());
|
||||
|
||||
TMapOptions options = TMapOptions::EMapOnly;
|
||||
if (button == m_secondaryButton.get())
|
||||
options |= TMapOptions::ECarRouting;
|
||||
|
||||
DownloadCountry(static_cast<int>(options));
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapEnded(m2::PointD const & pt)
|
||||
void CountryStatusDisplay::DownloadCountry(int options, bool checkCallback)
|
||||
{
|
||||
if (m_downloadButton->isVisible())
|
||||
return m_downloadButton->onTapEnded(pt);
|
||||
return false;
|
||||
ASSERT(m_countryIdx.IsValid(), ());
|
||||
if (checkCallback && m_downloadCallback)
|
||||
m_downloadCallback(options);
|
||||
else
|
||||
{
|
||||
if (IsStatusFailed())
|
||||
{
|
||||
m_progressSize = m_activeMaps.GetDownloadableCountrySize(m_countryIdx);
|
||||
m_activeMaps.RetryDownloading(m_countryIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
TMapOptions mapOptions = static_cast<TMapOptions>(options);
|
||||
m_progressSize = m_activeMaps.GetCountrySize(m_countryIdx, mapOptions);
|
||||
m_activeMaps.DownloadMap(m_countryIdx, mapOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::onTapCancelled(m2::PointD const & pt)
|
||||
void CountryStatusDisplay::Repaint() const
|
||||
{
|
||||
if (m_downloadButton->isVisible())
|
||||
return m_downloadButton->onTapCancelled(pt);
|
||||
return false;
|
||||
setIsDirtyLayout(true);
|
||||
const_cast<CountryStatusDisplay *>(this)->invalidate();
|
||||
}
|
||||
|
||||
bool CountryStatusDisplay::IsStatusFailed() const
|
||||
{
|
||||
return m_countryStatus == TStatus::EOutOfMemFailed || m_countryStatus == TStatus::EDownloadFailed;
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::Lock() const
|
||||
{
|
||||
#ifdef OMIM_OS_ANDROID
|
||||
m_mutex.Lock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CountryStatusDisplay::Unlock() const
|
||||
{
|
||||
#ifdef OMIM_OS_ANDROID
|
||||
m_mutex.Unlock();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,83 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include "../storage/storage.hpp"
|
||||
#include "active_maps_layout.hpp"
|
||||
|
||||
#include "../gui/element.hpp"
|
||||
#include "../gui/button.hpp"
|
||||
#include "../storage/storage_defines.hpp"
|
||||
|
||||
#ifdef OMIM_OS_ANDROID
|
||||
#include "../base/mutex.hpp"
|
||||
#endif
|
||||
|
||||
#include "../std/unique_ptr.hpp"
|
||||
|
||||
#include "../std/target_os.hpp"
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class Button;
|
||||
class TextView;
|
||||
}
|
||||
|
||||
class Framework;
|
||||
|
||||
namespace storage { struct TIndex; }
|
||||
|
||||
/// This class is a composite GUI element to display
|
||||
/// an on-screen GUI for the country, which is not downloaded yet.
|
||||
class CountryStatusDisplay : public gui::Element
|
||||
class CountryStatusDisplay : public gui::Element,
|
||||
public storage::ActiveMapsLayout::ActiveMapsListener
|
||||
{
|
||||
private:
|
||||
|
||||
/// Storage-related members and methods
|
||||
/// @{
|
||||
/// connection to the Storage for notifications
|
||||
unsigned m_slotID;
|
||||
storage::Storage * m_storage;
|
||||
/// notification callback upon country status change
|
||||
void CountryStatusChanged(storage::TIndex const &);
|
||||
/// notification callback upon country downloading progress
|
||||
void CountryProgress(storage::TIndex const &, pair<int64_t, int64_t> const & progress);
|
||||
/// @}
|
||||
|
||||
void UpdateStatusAndProgress();
|
||||
|
||||
/// download button
|
||||
unique_ptr<gui::Button> m_downloadButton;
|
||||
/// country status message
|
||||
unique_ptr<gui::TextView> m_statusMsg;
|
||||
|
||||
/// current map name, "Province" part of the fullName
|
||||
string m_mapName;
|
||||
/// current map group name, "Country" part of the fullName
|
||||
string m_mapGroupName;
|
||||
/// current country status
|
||||
storage::TStatus m_countryStatus;
|
||||
/// index of the country in Storage
|
||||
storage::TIndex m_countryIdx;
|
||||
/// downloading progress of the country
|
||||
pair<int64_t, int64_t> m_countryProgress;
|
||||
|
||||
bool m_notEnoughSpace;
|
||||
|
||||
string const displayName() const;
|
||||
|
||||
template <class T1, class T2>
|
||||
void SetStatusMessage(string const & msgID, T1 const * t1 = 0, T2 const * t2 = 0);
|
||||
|
||||
typedef gui::Element TBase;
|
||||
public:
|
||||
|
||||
struct Params : public gui::Element::Params
|
||||
{
|
||||
storage::Storage * m_storage;
|
||||
Params();
|
||||
Params(storage::ActiveMapsLayout & activeMaps) : m_activeMaps(activeMaps) {}
|
||||
|
||||
storage::ActiveMapsLayout & m_activeMaps;
|
||||
};
|
||||
|
||||
CountryStatusDisplay(Params const & p);
|
||||
~CountryStatusDisplay();
|
||||
|
||||
/// start country download
|
||||
void downloadCountry();
|
||||
/// set download button listener
|
||||
void setDownloadListener(gui::Button::TOnClickListener const & l);
|
||||
/// set current country name
|
||||
void setCountryIndex(storage::TIndex const & idx);
|
||||
void SetCountryIndex(storage::TIndex const & idx);
|
||||
typedef function<void (int)> TDownloadCountryFn;
|
||||
void SetDownloadCountryListener(TDownloadCountryFn const & fn) { m_downloadCallback = fn; }
|
||||
void DownloadCurrentCountry(int options);
|
||||
|
||||
/// @name Override from graphics::OverlayElement and gui::Element.
|
||||
//@{
|
||||
virtual void setIsVisible(bool isVisible) const;
|
||||
virtual void setIsDirtyLayout(bool isDirty) const;
|
||||
virtual m2::RectD GetBoundRect() const;
|
||||
|
||||
void setPivot(m2::PointD const & pv);
|
||||
void draw(graphics::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
|
||||
|
||||
void cache();
|
||||
|
@ -91,4 +64,57 @@ public:
|
|||
bool onTapEnded(m2::PointD const & pt);
|
||||
bool onTapCancelled(m2::PointD const & pt);
|
||||
//@}
|
||||
|
||||
private:
|
||||
virtual void CountryGroupChanged(storage::ActiveMapsLayout::TGroup const & oldGroup, int oldPosition,
|
||||
storage::ActiveMapsLayout::TGroup const & newGroup, int newPosition) {}
|
||||
virtual void CountryStatusChanged(storage::ActiveMapsLayout::TGroup const & group, int position);
|
||||
virtual void CountryOptionsChanged(storage::ActiveMapsLayout::TGroup const & group, int position){}
|
||||
virtual void DownloadingProgressUpdate(storage::ActiveMapsLayout::TGroup const & group, int position,
|
||||
storage::LocalAndRemoteSizeT const & progress);
|
||||
|
||||
template <class T1, class T2>
|
||||
string FormatStatusMessage(string const & msgID, T1 const * t1 = 0, T2 const * t2 = 0);
|
||||
|
||||
void FormatDisplayName(string const & mapName, string const & groupName);
|
||||
|
||||
void SetVisibilityForState() const;
|
||||
void SetContentForState();
|
||||
void SetContentForDownloadPropose();
|
||||
void SetContentForProgress();
|
||||
void SetContentForInQueue();
|
||||
void SetContentForError();
|
||||
|
||||
void ComposeElementsForState();
|
||||
|
||||
typedef function<bool (unique_ptr<gui::Button> const &, m2::PointD const &)> TTapActionFn;
|
||||
bool OnTapAction(TTapActionFn const & action, m2::PointD const & pt);
|
||||
|
||||
void OnButtonClicked(const Element * button);
|
||||
void DownloadCountry(int options, bool checkCallback = true);
|
||||
|
||||
void Repaint() const;
|
||||
|
||||
bool IsStatusFailed() const;
|
||||
|
||||
private:
|
||||
storage::ActiveMapsLayout & m_activeMaps;
|
||||
int m_activeMapsSlotID = 0;
|
||||
|
||||
unique_ptr<gui::TextView> m_label;
|
||||
unique_ptr<gui::Button> m_primaryButton;
|
||||
unique_ptr<gui::Button> m_secondaryButton;
|
||||
|
||||
string m_displayMapName;
|
||||
mutable storage::TStatus m_countryStatus = storage::TStatus::EUnknown;
|
||||
storage::TIndex m_countryIdx;
|
||||
storage::LocalAndRemoteSizeT m_progressSize;
|
||||
|
||||
TDownloadCountryFn m_downloadCallback;
|
||||
|
||||
void Lock() const;
|
||||
void Unlock() const;
|
||||
#ifdef OMIM_OS_ANDROID
|
||||
mutable threads::Mutex m_mutex;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
|
||||
#define DEFAULT_BOOKMARK_TYPE "placemark-red"
|
||||
|
||||
|
||||
using namespace storage;
|
||||
using namespace routing;
|
||||
using namespace location;
|
||||
|
@ -206,7 +205,8 @@ Framework::Framework()
|
|||
// Init strings bundle.
|
||||
m_stringsBundle.SetDefaultString("country_status_added_to_queue", "^\nis added to the downloading queue");
|
||||
m_stringsBundle.SetDefaultString("country_status_downloading", "Downloading\n^\n^%");
|
||||
m_stringsBundle.SetDefaultString("country_status_download", "Download\n^");
|
||||
m_stringsBundle.SetDefaultString("country_status_download", "Download map\n^ MB");
|
||||
m_stringsBundle.SetDefaultString("country_status_download_routing", "Download Map + Routing\n^ MB");
|
||||
m_stringsBundle.SetDefaultString("country_status_download_failed", "Downloading\n^\nhas failed");
|
||||
m_stringsBundle.SetDefaultString("try_again", "Try Again");
|
||||
m_stringsBundle.SetDefaultString("not_enough_free_space_on_sdcard", "Not enough space for downloading");
|
||||
|
@ -701,8 +701,8 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
|
|||
|
||||
if (isEmptyModel)
|
||||
m_informationDisplay.setEmptyCountryIndex(GetCountryIndex(GetViewportCenter()));
|
||||
|
||||
m_informationDisplay.enableCountryStatusDisplay(isEmptyModel);
|
||||
else
|
||||
m_informationDisplay.setEmptyCountryIndex(storage::TIndex());
|
||||
|
||||
bool const isCompassEnabled = my::Abs(ang::GetShortestDistance(m_navigator.Screen().GetAngle(), 0.0)) > my::DegToRad(3.0);
|
||||
bool const isCompasActionEnabled = m_informationDisplay.isCompassArrowEnabled() && m_navigator.InAction();
|
||||
|
@ -715,17 +715,12 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
|
|||
m_informationDisplay.setDebugInfo(0, drawScale);
|
||||
|
||||
m_informationDisplay.enableRuler(drawScale > 4 && !m_informationDisplay.isCopyrightActive());
|
||||
#ifdef DEBUG
|
||||
m_informationDisplay.enableDebugInfo(true);
|
||||
#endif
|
||||
|
||||
m_informationDisplay.doDraw(pDrawer);
|
||||
pScreen->endFrame();
|
||||
|
||||
m_bmManager.DrawItems(e);
|
||||
m_guiController->UpdateElements();
|
||||
m_guiController->DrawFrame(pScreen);
|
||||
|
||||
}
|
||||
|
||||
void Framework::DoPaint(shared_ptr<PaintEvent> const & e)
|
||||
|
|
|
@ -64,12 +64,11 @@ void InformationDisplay::InitRuler(Framework * fw)
|
|||
|
||||
void InformationDisplay::InitCountryStatusDisplay(Framework * fw)
|
||||
{
|
||||
CountryStatusDisplay::Params p;
|
||||
CountryStatusDisplay::Params p(fw->GetCountryTree().GetActiveMapLayout());
|
||||
|
||||
p.m_pivot = m2::PointD(0, 0);
|
||||
p.m_position = EPosCenter;
|
||||
p.m_depth = countryStatusDepth;
|
||||
p.m_storage = &fw->Storage();
|
||||
|
||||
m_countryStatusDisplay.reset(new CountryStatusDisplay(p));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue