Example #1
0
PixelRect GetButtonPosition(unsigned MenuID, const PixelRect& rcScreen) {
    PixelRect rc = rcScreen;
    rc.Grow(-1); // remove Margin

    unsigned i = MenuID - 1;
    
    assert(i < MenuButtons.size());
    
    const PixelScalar row   = ScreenLandscape ? LandscapeLayout[i].row : PortraitLayout[i].row;
    const PixelScalar col   = ScreenLandscape ? LandscapeLayout[i].col :PortraitLayout[i].col;
    const PixelScalar nbRow = ScreenLandscape ? 5 : 7;
    const PixelScalar nbCol = ScreenLandscape ? 5 : 4;

    const PixelSize size = {
        std::min<PixelScalar>((rc.GetSize().cx-(nbCol-1))/nbCol, NIBLSCALE(80)), 
        std::min<PixelScalar>((rc.GetSize().cy-nbRow-1)/nbRow, NIBLSCALE(40))
    };
    
    const double x_interval = (rc.GetSize().cx - size.cx * nbCol) / (nbCol-1);
    const double y_interval = (rc.GetSize().cy - size.cy * nbRow) / (nbRow-1);

    const RasterPoint origin = {
        rc.left + (PixelScalar)(col * (size.cx + x_interval)),
        rc.top + (PixelScalar)(row * (size.cy + y_interval))
    };

    return PixelRect(origin, size);
}
Example #2
0
void
WidgetDialog::AutoSize()
{
  const PixelRect parent_rc = GetParentClientRect();
  const PixelSize parent_size = parent_rc.GetSize();

  widget.Prepare();
  PixelSize min_size = widget.Get()->GetMinimumSize();
  min_size.cy += GetTitleHeight();
  PixelSize max_size = widget.Get()->GetMaximumSize();
  max_size.cy += GetTitleHeight();

  const PixelScalar min_height_with_buttons =
    min_size.cy + Layout::GetMaximumControlHeight();
  const PixelScalar max_height_with_buttons =
    max_size.cy + Layout::GetMaximumControlHeight();
  if (/* need full dialog height even for minimum widget height? */
      min_height_with_buttons >= parent_size.cy ||
      /* try to avoid putting buttons left on portrait screens; try to
         comply with maximum widget height only on landscape
         screens */
      (parent_size.cx > parent_size.cy &&
       max_height_with_buttons >= parent_size.cy)) {
    /* need full height, buttons must be left */
    PixelRect rc = parent_rc;
    if (max_size.cy < parent_size.cy)
      rc.bottom = rc.top + max_size.cy;

    PixelRect remaining = buttons.LeftLayout(rc);
    PixelSize remaining_size = remaining.GetSize();
    if (remaining_size.cx > max_size.cx)
      rc.right -= remaining_size.cx - max_size.cx;

    Move(rc);
    widget.Move(buttons.LeftLayout());
    return;
  }

  /* see if buttons fit at the bottom */

  PixelRect rc = parent_rc;
  if (max_size.cx < parent_size.cx)
    rc.right = rc.left + max_size.cx;

  PixelRect remaining = buttons.BottomLayout(rc);
  PixelSize remaining_size = remaining.GetSize();

  if (remaining_size.cy > max_size.cy)
    rc.bottom -= remaining_size.cy - max_size.cy;

  Move(rc);
  widget.Move(buttons.BottomLayout());
}
Example #3
0
void
KeyboardWidget::PrepareSize(const PixelRect &rc)
{
  const PixelSize new_size = rc.GetSize();
  button_width = new_size.cx / 10;
  button_height = new_size.cy / 5;
}
Example #4
0
void
Window::Create(ContainerWindow *parent, PixelRect rc,
               const WindowStyle window_style)
{
  assert(IsScreenInitialized());
  assert(rc.left <= rc.right);
  assert(rc.right - rc.left < 0x8000);
  assert(rc.top <= rc.bottom);
  assert(rc.bottom - rc.top < 0x8000);

  double_clicks = window_style.double_clicks;

  this->parent = parent;
  position = rc.GetOrigin();
  size = rc.GetSize();

  tab_stop = window_style.tab_stop;
  control_parent = window_style.control_parent;
  visible = window_style.visible;
  enabled = window_style.enabled;
  has_border = window_style.has_border;
  text_style = window_style.text_style;

  if (parent != NULL)
    parent->AddChild(*this);

  OnCreate();
  OnResize(size);
}
Example #5
0
static void
Draw(Canvas &canvas)
{
  PixelRect rc = canvas.GetRect();
  rc.Grow(-0.2 * rc.GetSize().cx);
  
  /* draw the banner text with a large font */
  Font small_font;
  small_font.LoadFile("/opt/LK8000/share/fonts/DejaVuSansCondensed.ttf", (rc.GetSize().cy / 25));
  canvas.Select(small_font);
  canvas.SetTextColor(COLOR_BLACK);
  canvas.SetBackgroundTransparent();

  const TCHAR *const text = _T("Powered Off");
  const PixelSize text_size = canvas.CalcTextSize(text);
  const RasterPoint text_pos = {
      rc.left + 16,
      rc.bottom - 16 - text_size.cy
  };
  canvas.DrawText(text_pos.x, text_pos.y, text);
  
  Font big_font;
  big_font.LoadFile("/opt/LK8000/share/fonts/DejaVuSansCondensed-Bold.ttf", (rc.GetSize().cy / 10));
  canvas.Select(big_font);
  
  const TCHAR *const text2 = _T("LK8000");
  const PixelSize text2_size = canvas.CalcTextSize(text2);
  const RasterPoint text2_pos = {
      (rc.left + rc.GetSize().cx + text2_size.cx) / 2,
      (rc.top + (rc.GetSize().cy / 10))
  };
  canvas.DrawText(text2_pos.x, text2_pos.y, text2);
  
  const double Scale = (double)rc.GetSize().cx / (double)bird_size.cx;
  
  RasterPoint polygon[array_size(bird_polygon)] = {};
  std::transform(std::begin(bird_polygon), std::end(bird_polygon), std::begin(polygon), [Scale, rc, text2_size, text2_pos]( const RasterPoint& pt ) {
      return RasterPoint(pt.x*Scale + rc.left, pt.y*Scale + text2_pos.y + text2_size.cy);
  });
  
  canvas.SelectBlackBrush();
  canvas.DrawPolygon(polygon, array_size(polygon));
}
Example #6
0
void
KeyboardWidget::OnResize(const PixelRect &rc)
{
  const PixelSize new_size = rc.GetSize();
  button_width = new_size.cx / 10;
  button_height = new_size.cy / 5;

  ResizeButtons();
  MoveButtons(rc);
}
Example #7
0
InfoBoxLayout::Layout
InfoBoxLayout::Calculate(PixelRect rc, InfoBoxSettings::Geometry geometry)
{
  const PixelSize screen_size = rc.GetSize();

  geometry = ValidateGeometry(geometry, screen_size);

  Layout layout;

  layout.geometry = geometry;
  layout.landscape = screen_size.cx > screen_size.cy;
  layout.count = geometry_counts[(unsigned)geometry];
  assert(layout.count <= InfoBoxSettings::Panel::MAX_CONTENTS);

  CalcInfoBoxSizes(layout, screen_size, geometry);

  layout.ClearVario();

  unsigned right = rc.right;

  switch (geometry) {
  case InfoBoxSettings::Geometry::SPLIT_8:
  case InfoBoxSettings::Geometry::OBSOLETE_SPLIT_8:
    if (layout.landscape) {
      rc.left = MakeLeftColumn(layout, layout.positions, 4,
                               rc.left, rc.top, rc.bottom);
      rc.right = MakeRightColumn(layout, layout.positions + 4, 4,
                                 rc.right, rc.top, rc.bottom);
    } else {
      rc.top = MakeTopRow(layout, layout.positions, 4,
                          rc.left, rc.right, rc.top);
      rc.bottom = MakeBottomRow(layout, layout.positions + 4, 4,
                                rc.left, rc.right, rc.bottom);
    }

    break;

  case InfoBoxSettings::Geometry::BOTTOM_8_VARIO:
    layout.vario.left = rc.right - layout.control_size.cx;
    layout.vario.right = rc.right;
    layout.vario.top = rc.bottom - layout.control_size.cy * 2;
    layout.vario.bottom = rc.bottom;

    right = layout.vario.left;

    /* fall through */

  case InfoBoxSettings::Geometry::BOTTOM_RIGHT_8:
  case InfoBoxSettings::Geometry::OBSOLETE_BOTTOM_RIGHT_8:
    if (layout.landscape) {
      rc.right = MakeRightColumn(layout, layout.positions + 4, 4,
                                 rc.right, rc.top, rc.bottom);
      rc.right = MakeRightColumn(layout, layout.positions, 4,
                                 rc.right, rc.top, rc.bottom);
    } else {
      rc.bottom = MakeBottomRow(layout, layout.positions + 4, 4,
                                rc.left, right, rc.bottom);
      rc.bottom = MakeBottomRow(layout, layout.positions, 4,
                                rc.left, right, rc.bottom);
    }

    break;

  case InfoBoxSettings::Geometry::TOP_8_VARIO:
    layout.vario.left = rc.right - layout.control_size.cx;
    layout.vario.right = rc.right;
    layout.vario.top = rc.top;
    layout.vario.bottom = rc.top + layout.control_size.cy * 2;

    right = layout.vario.left;

    /* fall through */

  case InfoBoxSettings::Geometry::TOP_LEFT_8:
  case InfoBoxSettings::Geometry::OBSOLETE_TOP_LEFT_8:
    if (layout.landscape) {
      rc.left = MakeLeftColumn(layout, layout.positions, 4,
                               rc.left, rc.top, rc.bottom);
      rc.left = MakeLeftColumn(layout, layout.positions + 4, 4,
                               rc.left, rc.top, rc.bottom);
    } else {
      rc.top = MakeTopRow(layout, layout.positions, 4,
                          rc.left, right, rc.top);
      rc.top = MakeTopRow(layout, layout.positions + 4, 4,
                          rc.left, right, rc.top);
    }

    break;

  case InfoBoxSettings::Geometry::LEFT_6_RIGHT_3_VARIO:
    layout.vario.left = rc.right - layout.control_size.cx;
    layout.vario.right = rc.right;
    layout.vario.top = 0;
    layout.vario.bottom = layout.vario.top + layout.control_size.cy * 3;

    rc.left = MakeLeftColumn(layout, layout.positions, 6,
                             rc.left, rc.top, rc.bottom);
    rc.right = MakeRightColumn(layout, layout.positions + 6, 3, rc.right,
                               rc.top + 3 * layout.control_size.cy, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::LEFT_12_RIGHT_3_VARIO:
    layout.vario.left = rc.right - layout.control_size.cx;
    layout.vario.right = rc.right;
    layout.vario.top = 0;
    layout.vario.bottom = layout.vario.top + layout.control_size.cy * 3;

    rc.right = MakeRightColumn(layout, layout.positions + 6, 3, rc.right,
                               rc.top + 3 * layout.control_size.cy, rc.bottom);

    layout.control_size.cx = layout.control_size.cy * 1.1;
    rc.left = MakeLeftColumn(layout, layout.positions, 6,
                             rc.left, rc.top, rc.bottom);
    rc.left = MakeLeftColumn(layout, layout.positions + 9, 6,
                             rc.left, rc.top, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::BOTTOM_RIGHT_12:
  case InfoBoxSettings::Geometry::OBSOLETE_BOTTOM_RIGHT_12:
    if (layout.landscape) {
      rc.right = MakeRightColumn(layout, layout.positions + 6, 6,
                                 rc.right, rc.top, rc.bottom);
      rc.right = MakeRightColumn(layout, layout.positions, 6,
                                 rc.right, rc.top, rc.bottom);
    } else {
      rc.bottom = MakeBottomRow(layout, layout.positions + 6, 6,
                                rc.left, rc.right, rc.bottom);
      rc.bottom = MakeBottomRow(layout, layout.positions, 6,
                                rc.left, rc.right, rc.bottom);
    }

    break;

  case InfoBoxSettings::Geometry::TOP_LEFT_12:
    if (layout.landscape) {
      rc.left = MakeLeftColumn(layout, layout.positions, 6,
                               rc.left, rc.top, rc.bottom);
      rc.left = MakeLeftColumn(layout, layout.positions + 6, 6,
                               rc.left, rc.top, rc.bottom);
    } else {
      rc.top = MakeTopRow(layout, layout.positions, 6,
                          rc.left, rc.right, rc.top);
      rc.top = MakeTopRow(layout, layout.positions + 6, 6,
                          rc.left, rc.right, rc.top);
    }
    break;

  case InfoBoxSettings::Geometry::RIGHT_16:
    rc.right = MakeRightColumn(layout, layout.positions + 8, 8,
                               rc.right, rc.top, rc.bottom);
    rc.right = MakeRightColumn(layout, layout.positions, 8,
                               rc.right, rc.top, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::RIGHT_24:
    rc.right = MakeRightColumn(layout, layout.positions + 16, 8,
                               rc.right, rc.top, rc.bottom);
    rc.right = MakeRightColumn(layout, layout.positions + 8, 8,
                               rc.right, rc.top, rc.bottom);
    rc.right = MakeRightColumn(layout, layout.positions, 8,
                               rc.right, rc.top, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::RIGHT_9_VARIO:
    layout.vario.left = rc.right - layout.control_size.cx;
    layout.vario.right = rc.right;
    layout.vario.top = 0;
    layout.vario.bottom = layout.vario.top + layout.control_size.cy * 3;

    rc.right = MakeRightColumn(layout, layout.positions + 6, 3,
                               rc.right,
                               rc.top + 3 * layout.control_size.cy, rc.bottom);
    rc.right = MakeRightColumn(layout, layout.positions, 6,
                               rc.right, rc.top, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::RIGHT_5:
    rc.right = MakeRightColumn(layout, layout.positions, 5,
                               rc.right, rc.top, rc.bottom);
    break;

  case InfoBoxSettings::Geometry::TOP_LEFT_4:
  case InfoBoxSettings::Geometry::OBSOLETE_TOP_LEFT_4:
    if (layout.landscape)
      rc.left = MakeLeftColumn(layout, layout.positions, 4,
                               rc.left, rc.top, rc.bottom);
    else
      rc.top = MakeTopRow(layout, layout.positions, 4,
                          rc.left, rc.right, rc.top);
    break;

  case InfoBoxSettings::Geometry::BOTTOM_RIGHT_4:
  case InfoBoxSettings::Geometry::OBSOLETE_BOTTOM_RIGHT_4:
    if (layout.landscape)
      rc.right = MakeRightColumn(layout, layout.positions, 4,
                                 rc.right, rc.top, rc.bottom);
    else
      rc.bottom = MakeBottomRow(layout, layout.positions, 4,
                                rc.left, rc.right, rc.bottom);
    break;
  };

  layout.remaining = rc;
  return layout;
}
Example #8
0
static void OnTaskPaintListItem(WindowControl * Sender, LKSurface& Surface){

  int n = UpLimit - LowLimit;
  TCHAR sTmp[120];
  TCHAR wpName[120];
  TCHAR landableStr[5] = TEXT(" [X]");
  // LKTOKEN _@M1238_ "L"
  landableStr[2] = MsgToken(1238)[0];
  LockTaskData();

  const PixelRect rcClient(Sender->GetClientRect());
  
  const int w0 = rcClient.GetSize().cx - DLGSCALE(1);
  const int w1 = Surface.GetTextWidth(TEXT(" 000km"));
  _stprintf(sTmp, _T("  000%s"), MsgToken(2179));
  const int w2 = Surface.GetTextWidth(sTmp);

  const int TextMargin = (rcClient.GetSize().cy - Surface.GetTextHeight(TEXT("A"))) / 2;

  const int p1 = w0-w1-w2- rcClient.GetSize().cy - DLGSCALE(2);
  const int p2 = w0-w2- rcClient.GetSize().cy - DLGSCALE(2);
  
  const PixelRect rc = {
      0, 
      0,
      rcClient.GetSize().cy, 
      rcClient.GetSize().cy
  };
  
  if (DrawListIndex < n){
    int i = LowLimit + DrawListIndex;
//    if ((WayPointList[Task[i].Index].Flags & LANDPOINT) >0)
//      MapWindow::DrawRunway(hDC,  &WayPointList[Task[i].Index],  rc, 3000,true);
    MapWindow::DrawTaskPicto(Surface, DrawListIndex,  rc, 2500);
    if (Task[i].Index>=0) {
      _stprintf(wpName, TEXT("%s%s"),
                WayPointList[Task[i].Index].Name,
                (WayPointList[Task[i].Index].Flags & LANDPOINT) ? landableStr : TEXT(""));

      if (AATEnabled && ValidTaskPoint(i+1) && (i>0)) {
        if (Task[i].AATType==0 || Task[i].AATType==3) {
          _stprintf(sTmp, TEXT("%s %.1f"),
                    wpName, Task[i].AATCircleRadius*DISTANCEMODIFY);
        } else {
          if(Task[i].AATType==2 && DoOptimizeRoute()) {
             _stprintf(sTmp, TEXT("%s %.1f/1"),
                    wpName, Task[i].PGConeSlope);
          } else {
             _stprintf(sTmp, TEXT("%s %.1f"),
                    wpName, Task[i].AATSectorRadius*DISTANCEMODIFY);
          }
        }
      } else {
        _stprintf(sTmp, TEXT("%s"), wpName);
      }

      Surface.SetBackgroundTransparent();
      Surface.SetTextColor(RGB_BLACK);
      Surface.DrawTextClip(rc.right + DLGSCALE(2), TextMargin, sTmp, p1-DLGSCALE(4));

      _stprintf(sTmp, TEXT("%.0f %s"),Task[i].Leg*DISTANCEMODIFY,Units::GetDistanceName());
      Surface.DrawText(rc.right+p1+w1-Surface.GetTextWidth(sTmp), TextMargin, sTmp);

      _stprintf(sTmp, TEXT("%d%s"),  iround(Task[i].InBound),MsgToken(2179));
      Surface.DrawText(rc.right +p2+w2-Surface.GetTextWidth(sTmp), TextMargin, sTmp);

    }

  } else {

    Surface.SetTextColor(RGB_BLACK);

     // if (DrawListIndex==n) { // patchout 091126
     if (DrawListIndex==n && UpLimit < MAXTASKPOINTS) { // patch 091126

	// LKTOKEN  _@M832_ = "add waypoint"
      _stprintf(sTmp, TEXT("  (%s)"), MsgToken(832));
      Surface.DrawText(rc.right +DLGSCALE(2), TextMargin, sTmp);
    } else if ((DrawListIndex==n+1) && ValidTaskPoint(0)) {

      if (!AATEnabled || ISPARAGLIDER) {
        // LKTOKEN  _@M735_ = "Total:"
        Surface.DrawText(rc.right +DLGSCALE(2), TextMargin, MsgToken(735));
	   _stprintf(sTmp, TEXT("%.0f %s%s"), lengthtotal*DISTANCEMODIFY, Units::GetDistanceName(), fai_ok?_T(" FAI"):_T(""));
	
       Surface.DrawText(rc.right +p1+w1-Surface.GetTextWidth(sTmp), TextMargin, sTmp);

      } else {

      double d1 = CALCULATED_INFO.TaskDistanceToGo;
      if ((CALCULATED_INFO.TaskStartTime>0.0) && (CALCULATED_INFO.Flying) && (ActiveTaskPoint>0)) {
                   d1 += CALCULATED_INFO.TaskDistanceCovered;
      }

	if (d1==0.0) {
	  d1 = CALCULATED_INFO.AATTargetDistance;
	}

	_stprintf(sTmp, TEXT("%s %.0f min %.0f (%.0f) %s"),
	// LKTOKEN  _@M735_ = "Total:"
                  MsgToken(735),
                  AATTaskLength*1.0,
		  DISTANCEMODIFY*lengthtotal,
		  DISTANCEMODIFY*d1,
		  Units::GetDistanceName());
	Surface.DrawText(rc.right +DLGSCALE(2), TextMargin, sTmp);
      }
    }
  }
  UnlockTaskData();

}
Example #9
0
//
//  FUNCTION: InitInstance()
//
//  PURPOSE: creates main window
//
//  COMMENTS:
//
//    In this function, we create and display the main program window.
//
BOOL InitInstance()
{
  extern bool CommandResolution;
  if(!IsEmbedded() && !CommandResolution) {
      ScreenSizeX = 800;
      ScreenSizeY = 480;
  }

#if defined(ENABLE_SDL) && defined(USE_FULLSCREEN)
 #if (SDL_MAJOR_VERSION >= 2)
  SDL_DisplayMode mode = {};
  if(SDL_GetCurrentDisplayMode(0, &mode) == 0) {
  	ScreenSizeX = mode.w;
    ScreenSizeY = mode.h;
  } else {
  	fprintf(stderr, "SDL_GetCurrentDisplayMode() has failed: %s\n", ::SDL_GetError());
  }
  #else
  	ScreenSizeX = 0;
    ScreenSizeY = 0;
  #endif
#endif

  PreloadInitialisation(true);

  RECT WindowSize;

#ifdef __linux__
  WindowSize=WindowResize(ScreenSizeX, ScreenSizeY);
#endif
#ifdef WIN32
#ifdef UNDER_CE
  WindowSize=WindowResize( GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
#else
  WindowSize=WindowResize(ScreenSizeX, ScreenSizeY);
#endif
#endif


  if (!goInstallSystem) Poco::Thread::sleep(50); // 091119
  #if TESTBENCH
  StartupStore(TEXT(". Create main window%s"),NEWLINE);
  #endif

  if(!MainWindow.Create(WindowSize)) {
      StartupStore(TEXT(". FAILURE: Create main window%s"),NEWLINE);
      return FALSE;
  }
  const PixelRect rc(MainWindow.GetClientRect());
  ScreenSizeX = rc.GetSize().cx;
  ScreenSizeY = rc.GetSize().cy;
  
  InitLKScreen();
  InitLKFonts(); // causing problems with CreateButtonLabels?

  LKLoadFixedBitmaps();
  LKLoadProfileBitmaps();
  LKObjects_Create(); 


  ButtonLabel::CreateButtonLabels(rc);
  ButtonLabel::SetLabelText(0,TEXT("MODE"));

  extern void InitLKFonts();
  // reload updating LK fonts after loading profile for fontquality
  InitLKFonts();	

  ButtonLabel::SetFont(MapWindowBoldFont);

  Message::Initialize(rc); // creates window, sets fonts

  MainWindow.SetVisible(true);

  return TRUE;
}
Example #10
0
//
//  FUNCTION: InitInstance()
//
//  PURPOSE: creates main window
//
//  COMMENTS:
//
//    In this function, we create and display the main program window.
//
BOOL InitInstance()
{
  extern bool CommandResolution;
  if(!IsEmbedded() && !CommandResolution) {
      ScreenSizeX = 800;
      ScreenSizeY = 480;
  }

#if defined(ENABLE_SDL) && defined(USE_FULLSCREEN)
 #if (SDL_MAJOR_VERSION >= 2)
  SDL_DisplayMode mode = {};
  if(SDL_GetCurrentDisplayMode(0, &mode) == 0) {
	ScreenSizeX = mode.w;
    ScreenSizeY = mode.h;
  } else {
	fprintf(stderr, "SDL_GetCurrentDisplayMode() has failed: %s\n", ::SDL_GetError());
  }
  #else
	ScreenSizeX = 0;
    ScreenSizeY = 0;
  #endif
#endif

  PreloadInitialisation(true);

  RECT WindowSize;

#ifdef __linux__
#ifdef USE_VIDEOCORE
  uint32_t iWidth, iHeight;
  if(graphics_get_display_size(0, &iWidth, &iHeight) >= 0) {
    ScreenSizeX=iWidth;
    ScreenSizeY=iHeight;
  }
#endif
#ifdef ANDROID
  const PixelSize Size = native_view->GetSize();
  ScreenSizeX=Size.cx;
  ScreenSizeY=Size.cy;
#endif


  WindowSize=WindowResize(ScreenSizeX, ScreenSizeY);
#endif
#ifdef WIN32
#if defined(UNDER_CE) || defined(USE_FULLSCREEN)
  WindowSize=WindowResize( GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
#else
  WindowSize=WindowResize(ScreenSizeX, ScreenSizeY);
#endif
#endif

  #if TESTBENCH
  StartupStore(TEXT(". Create main window%s"),NEWLINE);
  #endif

  if(!MainWindow.Create(WindowSize)) {
      StartupStore(TEXT(". FAILURE: Create main window%s"),NEWLINE);
      return FALSE;
  }
  const PixelRect rc(MainWindow.GetClientRect());
  ScreenSizeX = rc.GetSize().cx;
  ScreenSizeY = rc.GetSize().cy;
  ScreenHasChanged();

  InitLKScreen();
  InitLKFonts(); // causing problems with CreateButtonLabels?

  LKLoadFixedBitmaps();
  LKLoadProfileBitmaps();
  LKObjects_Create();

  ButtonLabel::CreateButtonLabels(rc);
  ButtonLabel::SetFont(MapWindowBoldFont);

  Message::Initialize(rc); // creates window, sets fonts

  MainWindow.SetVisible(true);

  return TRUE;
}
Example #11
0
void MapWindow::LKDrawVario(LKSurface& Surface, const RECT& rc) {

    static PixelRect vrc, mrc, hrc, htrc, hbrc;

    static BrushReference greenBrush, darkyellowBrush, orangeBrush, redBrush;
    static BrushReference lakeBrush, blueBrush, indigoBrush;

    static PenReference borderPen; // Pen for border of vario bar and vario bricks ( white or black)
    static BrushReference forgroundBrush; // Brush used for draw middle thick or monochrome brick ( same color of borderPen )

    /* 
     * this array define vario Value for each brick, ( positive value )
     *  Number of brick for positive value is defined by this array size.
     */
    static const double positive_vario_step[] = {0.05, 0.25, 0.50, 0.75, 1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00, 3.50, 4.50, 5.00, 6.00, 7.00};
    static const unsigned positive_brick_count = array_size(positive_vario_step);

    static BrushReference positiveBrush[positive_brick_count];
    static PixelRect positiveBricks[positive_brick_count];

    /* 
     * this array define vario Value for each brick, ( negative value )
     *  Number of brick for negative value is defined by this array size.
     */
    static const double negative_vario_step[] = {-0.05, -0.25, -0.50, -0.75, -1.00, -1.25, -1.50, -1.75, -2.00, -2.50, -3.00, -3.50, -4.50, -5.00, -6.00, -7.00};
    static const unsigned negative_brick_count = array_size(negative_vario_step);

    static BrushReference negativeBrush[negative_brick_count];
    static PixelRect negativeBricks[negative_brick_count];

    static short startInitCounter = 0;
    static bool dogaugeinit = true;
    static double max_positiveGload;
    static double max_negativeGload;

    if (DoInit[MDI_DRAWVARIO]) {

        const int boxthick = IBLSCALE(BOXTHICK);
        const int hpixelseparate = (LKVarioBar > vBarVarioGR) ? 0 : IBLSCALE(PIXELSEPARATE);
        const int vpixelseparate = IBLSCALE(PIXELSEPARATE);
        const int variowidth = LKVarioSize;

        startInitCounter = 0;
        dogaugeinit = true;

        // initial fullscale G loads for 2D driving.
        // These values are then rescaled (only increased) automatically.
        max_positiveGload = 0.1;
        max_negativeGload = -0.1;


        borderPen = (BgMapColor > POSCOLOR) ? LKPen_White_N0 : LKPen_Black_N0;
        forgroundBrush = (BgMapColor > POSCOLOR) ? LKBrush_White : LKBrush_Black;
        
        greenBrush = LKBrush_Green;
        darkyellowBrush = LKBrush_DarkYellow2;
        orangeBrush = LKBrush_Orange;
        redBrush = LKBrush_Red;
        lakeBrush = LKBrush_Lake;
        blueBrush = LKBrush_Blue;
        indigoBrush = LKBrush_Indigo;


        const short lkvariobar = (LKVarioBar > vBarVarioGR) ? LKVarioBar - vBarVarioGR : LKVarioBar;
        switch (lkvariobar) {
            default:
                LKASSERT(false); // wrong config value or disabled, in any case, it's BUG
                // no break; for avoid to have unitialized Brush array.
            case vBarVarioColor:
                // set default background in case of missing values
                std::fill(std::begin(positiveBrush), std::end(positiveBrush), forgroundBrush);
                std::fill(std::begin(negativeBrush), std::end(negativeBrush), forgroundBrush);
                
                static_assert(array_size(positiveBrush)> 15, "\"positiveBrush\" size must be greater than 15, check \"positive_vario_step\" size");
                
                positiveBrush[15] = redBrush;
                positiveBrush[14] = redBrush;
                positiveBrush[13] = redBrush;
                positiveBrush[12] = redBrush;
                positiveBrush[11] = orangeBrush;
                positiveBrush[10] = orangeBrush;
                positiveBrush[9] = orangeBrush;
                positiveBrush[8] = orangeBrush;
                positiveBrush[7] = darkyellowBrush;
                positiveBrush[6] = darkyellowBrush;
                positiveBrush[5] = darkyellowBrush;
                positiveBrush[4] = darkyellowBrush;
                positiveBrush[3] = greenBrush;
                positiveBrush[2] = greenBrush;
                positiveBrush[1] = greenBrush;
                positiveBrush[0] = greenBrush;

                negativeBrush[0] = lakeBrush;
                negativeBrush[1] = lakeBrush;
                negativeBrush[2] = lakeBrush;
                negativeBrush[3] = lakeBrush;
                negativeBrush[4] = blueBrush;
                negativeBrush[5] = blueBrush;
                negativeBrush[6] = blueBrush;
                negativeBrush[7] = blueBrush;
                negativeBrush[8] = indigoBrush;
                negativeBrush[9] = indigoBrush;
                negativeBrush[10] = indigoBrush;
                negativeBrush[11] = indigoBrush;
                negativeBrush[12] = forgroundBrush;
                negativeBrush[13] = forgroundBrush;
                negativeBrush[14] = forgroundBrush;
                negativeBrush[15] = forgroundBrush;

                static_assert(array_size(negativeBrush)> 15, "\"negativeBrush\" size must be greater than 15, check \"negative_vario_step\" size");

                break;
            case vBarVarioMono:
                std::fill(std::begin(positiveBrush), std::end(positiveBrush), forgroundBrush);
                std::fill(std::begin(negativeBrush), std::end(negativeBrush), forgroundBrush);
                break;
            case vBarVarioRB:
                std::fill(std::begin(positiveBrush), std::end(positiveBrush), redBrush);
                std::fill(std::begin(negativeBrush), std::end(negativeBrush), blueBrush);
                break;
            case vBarVarioGR:
                std::fill(std::begin(positiveBrush), std::end(positiveBrush), greenBrush);
                std::fill(std::begin(negativeBrush), std::end(negativeBrush), redBrush);
                break;
        }

        // vario paint area
        vrc.left = rc.left;
        vrc.top = rc.top;
        vrc.right = vrc.left + variowidth;
        vrc.bottom = rc.bottom - BottomSize;

        // meter area
        mrc.left = vrc.left + hpixelseparate;
        mrc.top = vrc.top + vpixelseparate;
        mrc.right = vrc.right - hpixelseparate;
        mrc.bottom = vrc.bottom - vpixelseparate;

        // half vario separator for positive and negative values
        const double vmiddle_height = NIBLSCALE(2) - ((mrc.bottom - mrc.top) % 2);
        const double vmiddle = ((mrc.bottom - mrc.top) / 2.0) + mrc.top;

        hrc.top = vrc.top + vmiddle - (vmiddle_height / 2);
        hrc.bottom = vrc.top + vmiddle + (vmiddle_height / 2);
        hrc.left = vrc.left;
        hrc.right = vrc.right;

        // half top meter area
        htrc.left = mrc.left;
        htrc.right = mrc.right;
        htrc.bottom = hrc.top - vpixelseparate;
        htrc.top = mrc.top + vpixelseparate;

        // half bottom meter area
        hbrc.left = mrc.left;
        hbrc.right = mrc.right;
        hbrc.top = hrc.bottom + vpixelseparate;
        hbrc.bottom = mrc.bottom - vpixelseparate;

        // pixel height of each positive brick
        const int positive_brick_size = (htrc.bottom - htrc.top - (boxthick * (positive_brick_count - 1))) / positive_brick_count;
        const int positive_brick_advance = positive_brick_size + boxthick;

        // Pre-calculate brick positions for half top
        for (unsigned i = 0; i < positive_brick_count; ++i) {
            RECT& brc = positiveBricks[i];
            brc.left = htrc.left;
            brc.right = htrc.right - NIBLSCALE(4);
            brc.bottom = htrc.bottom - (i * positive_brick_advance);
            brc.top = brc.bottom - positive_brick_size;
        }
        // update last box for hide rounding artefact 
        positiveBricks[positive_brick_count - 1].top = htrc.top;

        // pixel height of each negative brick
        const int negative_brick_size = (hbrc.bottom - hbrc.top - (boxthick * (negative_brick_count - 1))) / negative_brick_count;
        const int negative_brick_advance = negative_brick_size + boxthick;

        // Pre-calculate brick positions for half bottom
        for (unsigned i = 0; i < negative_brick_count; ++i) {
            RECT& brc = negativeBricks[i];
            brc.left = hbrc.left;
            brc.right = hbrc.right - NIBLSCALE(4);
            brc.top = hbrc.top + (i * negative_brick_advance);
            brc.bottom = brc.top + negative_brick_size;
        }
        // update last box for hide rounding artefact 
        negativeBricks[negative_brick_count - 1].bottom = hbrc.bottom;

        DoInit[MDI_DRAWVARIO] = false;
    } // END of INIT

    double vario_value = 0; // can be vario, vario netto or STF offset, depending of config and map mode
    double mc_value = 0; // current MacCready value, used only for Vario or VarioNetto.

    if (ISCAR && DrawInfo.Speed > 0) {
        // Heading is setting Gload, but Heading is not calculated while steady!
        // For this case, we force vario_value to 0.
        //
        // Since we use currently a scale 0-6 for vario, we can use 0-2 for cars.
        // This accounts for an acceleration topscale of 0-100kmh in 13.9 seconds.
        // Not a big acceleration, but very good for normal car usage.
        // We make this concept dynamical, and different for positive and negative accelerations.
        // Because negative accelerations are much higher, on a car. Of course!
        //
        if (DerivedDrawInfo.Gload > 0) {
            if (DerivedDrawInfo.Gload > max_positiveGload) {
                max_positiveGload = DerivedDrawInfo.Gload;
                StartupStore(_T("..... NEW MAXPOSITIVE G=%f\n"), max_positiveGload);
            }
            LKASSERT(max_positiveGload > 0);
            vario_value = (DerivedDrawInfo.Gload / max_positiveGload)*6;
            //StartupStore(_T("Speed=%f G=%f max=%f val=%f\n"),DrawInfo.Speed, DerivedDrawInfo.Gload, max_positiveGload,vario_value);
        }
        if (DerivedDrawInfo.Gload < 0) {
            if (DerivedDrawInfo.Gload < max_negativeGload) {
                max_negativeGload = DerivedDrawInfo.Gload;
                StartupStore(_T("..... NEW MAXNEGATIVE G=%f\n"), max_negativeGload);
            }
            LKASSERT(max_negativeGload < 0);
            vario_value = (DerivedDrawInfo.Gload / max_negativeGload)*-6;
            //StartupStore(_T("Speed=%f G=%f max=%f val=%f\n"),DrawInfo.Speed, DerivedDrawInfo.Gload, max_negativeGload,vario_value);
        }

    } else if (MapWindow::mode.Is(MapWindow::Mode::MODE_CIRCLING) || LKVarioVal == vValVarioVario) {
        if (DrawInfo.VarioAvailable) {
            // UHM. I think we are not painting values correctly for knots &c.
            //vario_value = LIFTMODIFY*DrawInfo.Vario;
            vario_value = DrawInfo.Vario;
        } else {
            vario_value = DerivedDrawInfo.Vario;
        }
        mc_value = MACCREADY;
    } else {
        switch (LKVarioVal) {
            default:
            case vValVarioNetto:
                vario_value = DerivedDrawInfo.NettoVario;
                // simple hack for avoid to used polar curve : glider_sink_rate = Vario - NettoVario;
                mc_value = MACCREADY + (DerivedDrawInfo.Vario - DerivedDrawInfo.NettoVario);
                break;
            case vValVarioSoll:
                double ias;
                if (DrawInfo.AirspeedAvailable && DrawInfo.VarioAvailable)
                    ias = DrawInfo.IndicatedAirspeed;
                else
                    ias = DerivedDrawInfo.IndicatedAirspeedEstimated;

                // m/s 0-nnn autolimit to 20m/s full scale (72kmh diff)
                vario_value = clamp(DerivedDrawInfo.VOpt - ias, -20., 20.);
                vario_value /= 3.3333; // 0-20  -> 0-6
                vario_value *= -1; // if up, push down
                break;
        }
    }


    // Backup selected Brush & Pen
    LKSurface::OldPen oldPen = Surface.SelectObject(LK_NULL_PEN);
    LKSurface::OldBrush oldBrush = Surface.SelectObject(LKBrush_Hollow);
    
    // draw Vario box ( only if not transparent )
    if (LKVarioBar <= vBarVarioGR) {
        Surface.SelectObject(borderPen);
        Surface.SelectObject(hInvBackgroundBrush[BgMapColor]);
        Surface.Rectangle(vrc.left, vrc.top, vrc.right, vrc.bottom);
    }
    // draw middle separator for 0 scale indicator
    Surface.FillRect(&hrc, forgroundBrush);

    Surface.SelectObject(borderPen);
    if (dogaugeinit) {

        // this is causing problems on emulators and condor and most of the times when the gps has no valid date
        // so we don't use seconds, but loop counter
        if (startInitCounter++ > 2) {
            dogaugeinit = false;
        }

        // Demo show all bricks
        for (unsigned i = 0; i < positive_brick_count; ++i) {
            const RECT& brc = positiveBricks[i];
            Surface.SelectObject(positiveBrush[i]);
            Surface.Rectangle(brc.left, brc.top, brc.right, brc.bottom);
        }

        for (unsigned i = 0; i < negative_brick_count; ++i) {
            const RECT& brc = negativeBricks[i];
            Surface.SelectObject(negativeBrush[i]);
            Surface.Rectangle(brc.left, brc.top, brc.right, brc.bottom);
        }

    } else {
        // Draw Real Vario Data

        // Draw Positive Brick 
        for (unsigned i = 0; i < positive_brick_count && vario_value >= positive_vario_step[i]; ++i) {
            const RECT& brc = positiveBricks[i];
            Surface.SelectObject(positiveBrush[i]);
            Surface.Rectangle(brc.left, brc.top, brc.right, brc.bottom);
        }

        // Draw Negative Brick 
        for (unsigned i = 0; i < negative_brick_count && vario_value <= negative_vario_step[i]; ++i) {
            const RECT& brc = negativeBricks[i];
            Surface.SelectObject(negativeBrush[i]);
            Surface.Rectangle(brc.left, brc.top, brc.right, brc.bottom);
        }

        // Draw MacCready Indicator
        const auto step_iterator = std::upper_bound(std::begin(positive_vario_step), std::end(positive_vario_step), mc_value);
        size_t mc_brick_idx = std::distance(std::begin(positive_vario_step), step_iterator);
        if (mc_brick_idx > 1) {
            const PixelRect& brc_next = positiveBricks[mc_brick_idx];
            const PixelRect& brc_Prev = positiveBricks[mc_brick_idx-1];
            
            const PixelSize IconSize = hMcVario.GetSize();
            const PixelSize DrawSize = {
                vrc.GetSize().cx,
                IconSize.cy * vrc.GetSize().cx / IconSize.cx
            };
            const RasterPoint DrawPos = {
                vrc.left,
                brc_Prev.top + ((brc_next.bottom - brc_Prev.top) / 2) + (IconSize.cy / 2)
            };
            hMcVario.Draw(Surface, DrawPos.x, DrawPos.y, DrawSize.cx, DrawSize.cy);
        }
    }
    // cleanup
    Surface.SelectObject(oldPen);
    Surface.SelectObject(oldBrush);
}