about summary refs log blame commit diff stats
path: root/src/area_popup.cpp
blob: 9cc1208ccd0af49ed0ac396735c6d0e5efdabb62 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                        
                    
                     
                      
                   
                  
                           
                          
                          
                                                   
                                                             
                                       
              
 
                                            
                      
 
                                
         
                                               
                                                          
                     
 
                                    
                                                    
 
                                                         
                               
                                  
                                                             
                                                           
                    
                           
 
                                                                         
                                  
                                                                  
                                                                 
 
                                        
                                   





                                                                    
     

                                                             
                                                                     





                                             
                                                                 
                                                                     
                                                                       
                                                                       






                                               
                                                                                
 
        






                                                         
                                  
                                     
                                                                              
 
                                                           
 
                           


                                                                 


                                               




                                                                            



                                                                             
 
                                                                      
 
                                                           
 
                                                                  
                                                             
                                          
 

                                                             
                                                                           
 
                                   
   
 
                                                                 
                                                                     
 
                                                        

                                                               
                                                                             
                                                                        
                                                             
 
                                                                       
                                                                             
 
                                     
     

                                              
                             
                                 
 
               
 





                                                        


                                                                               
 
#include "area_popup.h"

#include <wx/dcbuffer.h>

#include <algorithm>

#include "ap_state.h"
#include "game_data.h"
#include "global.h"
#include "icons.h"
#include "tracker_config.h"
#include "tracker_panel.h"
#include "tracker_state.h"

AreaPopup::AreaPopup(wxWindow* parent, int area_id)
    : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) {
  SetBackgroundStyle(wxBG_STYLE_PAINT);

  LoadIcons();

  // TODO: This is slow on high-DPI screens.
  SetScrollRate(5, 5);

  SetBackgroundColour(*wxBLACK);
  Hide();

  Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this);
  Bind(wxEVT_DPI_CHANGED, &AreaPopup::OnDPIChanged, this);

  UpdateIndicators();
}

void AreaPopup::UpdateIndicators() {
  const MapArea& map_area = GD_GetMapArea(area_id_);

  wxFont the_font = GetFont().Scale(GetDPIScaleFactor());

  // Start calculating extents.
  wxMemoryDC mem_dc;
  mem_dc.SetFont(the_font.Bold());
  wxSize header_extent = mem_dc.GetTextExtent(map_area.name);

  int acc_height = header_extent.GetHeight() + FromDIP(20);
  int col_width = 0;

  mem_dc.SetFont(the_font);

  TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());

  std::vector<int> real_locations;

  for (int section_id = 0; section_id < map_area.locations.size();
       section_id++) {
    const Location& location = map_area.locations.at(section_id);

    if (tracker_panel->IsPanelsMode()) {
      if (!location.single_panel) {
        continue;
      }
    } else {
      if (!AP_IsLocationVisible(location.classification) &&
          !(location.hunt && GetTrackerConfig().show_hunt_panels)) {
        continue;
      }
    }

    real_locations.push_back(section_id);

    wxSize item_extent = mem_dc.GetTextExtent(location.name);
    int item_height =
        std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10);
    acc_height += item_height;

    if (item_extent.GetWidth() > col_width) {
      col_width = item_extent.GetWidth();
    }
  }

  if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) {
    for (int painting_id : map_area.paintings) {
      const PaintingExit& painting = GD_GetPaintingExit(painting_id);
      wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
      int item_height =
          std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10);
      acc_height += item_height;

      if (item_extent.GetWidth() > col_width) {
        col_width = item_extent.GetWidth();
      }
    }
  }

  int item_width = col_width + FromDIP(10 + 32);
  int full_width = std::max(header_extent.GetWidth(), item_width) + FromDIP(20);

  Fit();
  SetVirtualSize(full_width, acc_height);

  rendered_ = wxBitmap(full_width, acc_height);
  mem_dc.SelectObject(rendered_);
  mem_dc.SetPen(*wxTRANSPARENT_PEN);
  mem_dc.SetBrush(*wxBLACK_BRUSH);
  mem_dc.DrawRectangle({0, 0}, {full_width, acc_height});

  mem_dc.SetFont(the_font.Bold());
  mem_dc.SetTextForeground(*wxWHITE);
  mem_dc.DrawText(map_area.name,
                  {(full_width - header_extent.GetWidth()) / 2, FromDIP(10)});

  int cur_height = header_extent.GetHeight() + FromDIP(20);

  mem_dc.SetFont(the_font);

  for (int section_id : real_locations) {
    const Location& location = map_area.locations.at(section_id);

    bool checked = false;
    if (IsLocationWinCondition(location)) {
      checked = AP_HasReachedGoal();
    } else if (tracker_panel->IsPanelsMode()) {
      const Panel& panel = GD_GetPanel(*location.single_panel);
      if (panel.non_counting) {
        checked = AP_HasCheckedGameLocation(location.ap_location_id);
      } else {
        checked = tracker_panel->GetSolvedPanels().contains(panel.nodepath);
      }
    } else {
      checked =
          AP_HasCheckedGameLocation(location.ap_location_id) ||
          (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id));
    }

    const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_;

    mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), cur_height});

    bool reachable = IsLocationReachable(location.ap_location_id);
    const wxColour* text_color = reachable ? wxWHITE : wxRED;
    mem_dc.SetTextForeground(*text_color);

    wxSize item_extent = mem_dc.GetTextExtent(location.name);
    mem_dc.DrawText(
        location.name,
                    {FromDIP(10 + 32 + 10),
         cur_height + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});

    cur_height += FromDIP(10 + 32);
  }

  if (AP_IsPaintingShuffle() && !tracker_panel->IsPanelsMode()) {
    for (int painting_id : map_area.paintings) {
      const PaintingExit& painting = GD_GetPaintingExit(painting_id);

      bool reachable = IsPaintingReachable(painting_id);
      const wxColour* text_color = reachable ? wxWHITE : wxRED;
      mem_dc.SetTextForeground(*text_color);

      bool checked = reachable && AP_IsPaintingChecked(painting.internal_id);
      const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_;
      mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), cur_height});

      wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
      mem_dc.DrawText(painting.display_name,
                      {FromDIP(10 + 32 + 10),
           cur_height + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});

      cur_height += FromDIP(10 + 32);
    }
  }
}

void AreaPopup::OnPaint(wxPaintEvent& event) {
  wxBufferedPaintDC dc(this);
  PrepareDC(dc);
  dc.DrawBitmap(rendered_, 0, 0);

  event.Skip();
}

void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) {
  LoadIcons();
  UpdateIndicators();
}

void AreaPopup::LoadIcons() {
  unchecked_eye_ = GetTheIconCache().GetIcon("assets/unchecked.png",
                                             FromDIP(wxSize{32, 32}));
  checked_eye_ =
      GetTheIconCache().GetIcon("assets/checked.png", FromDIP(wxSize{32, 32}));
}