示例#1
0
wxSize wxRibbonPanel::DoGetNextSmallerSize(wxOrientation direction,
                                         wxSize relative_to) const
{
    if(m_expanded_panel != NULL)
    {
        // Next size depends upon children, who are currently in the
        // expanded panel
        return m_expanded_panel->DoGetNextSmallerSize(direction, relative_to);
    }

    // TODO: Check for, and delegate to, a sizer

    // Simple (and common) case of single ribbon child
    if(GetChildren().GetCount() == 1)
    {
        wxWindow* child = GetChildren().Item(0)->GetData();
        wxRibbonControl* ribbon_child = wxDynamicCast(child, wxRibbonControl);
        if(m_art != NULL && ribbon_child != NULL)
        {
            wxClientDC dc((wxRibbonPanel*) this);
            wxSize child_relative = m_art->GetPanelClientSize(dc, this, relative_to, NULL);
            wxSize smaller = ribbon_child->GetNextSmallerSize(direction, child_relative);
            if(smaller == child_relative)
            {
                if(CanAutoMinimise())
                {
                    wxSize minimised = m_minimised_size;
                    switch(direction)
                    {
                    case wxHORIZONTAL:
                        minimised.SetHeight(relative_to.GetHeight());
                        break;
                    case wxVERTICAL:
                        minimised.SetWidth(relative_to.GetWidth());
                        break;
                    default:
                        break;
                    }
                    return minimised;
                }
                else
                {
                    return relative_to;
                }
            }
            else
            {
                return m_art->GetPanelSize(dc, this, smaller, NULL);
            }
        }
    }

    // Fallback: Decrease by 20% (or minimum size, whichever larger)
    wxSize current(relative_to);
    wxSize minimum(GetMinSize());
    if(direction & wxHORIZONTAL)
    {
        current.x = (current.x * 4) / 5;
        if(current.x < minimum.x)
        {
            current.x = minimum.x;
        }
    }
    if(direction & wxVERTICAL)
    {
        current.y = (current.y * 4) / 5;
        if(current.y < minimum.y)
        {
            current.y = minimum.y;
        }
    }
    return current;
}
示例#2
0
void ToolBar::OnMotion( wxMouseEvent & event )
{
   // Go ahead and set the event to propagate
   event.Skip();

   // Don't do anything if we're not docked
   if( !IsDocked() )
   {
      return;
   }

   // Retrieve the mouse position
   wxPoint pos = ClientToScreen( event.GetPosition() );

   if( !HasCapture() )
   {
      if( IsResizable() )
      {
         wxPoint pos = event.GetPosition();
         wxRect rect = GetRect();

         // Adjust to size of resize grabber
         rect.x = rect.width - RWIDTH;
         rect.y = 0;
         rect.width = RWIDTH;

         // Is left click within resize grabber?
         if( rect.Contains( pos ) )
         {
            SetCursor( wxCURSOR_SIZEWE );
         }
         else
         {
            SetCursor( wxCURSOR_ARROW );
         }
      }
   }
   else if( event.Dragging() )
   {
      wxRect r = GetRect();
      wxSize msz = GetMinSize();
      wxSize psz = GetParent()->GetClientSize();

      // Adjust the size by the difference between the
      // last mouse and current mouse positions.
      r.width += ( pos.x - mResizeStart.x );

      // Constrain
      if( r.width < msz.x )
      {
         // Don't allow resizing to go too small
         r.width = msz.x;
      }
      else if( r.GetRight() > psz.x - 3 )
      {
         // Don't allow resizing to go too large
         //
         // The 3 magic pixels are because I'm too chicken to change the
         // calculations in ToolDock::LayoutToolBars() even though I'm
         // the one that set them up.  :-)
         r.SetRight( psz.x - 3 );
      }
      else
      {         
         // Remember for next go round
         mResizeStart = pos;
      }

      // Resize the bar
      SetSize( r.GetSize() );

      // Tell everyone we've changed sizes
      Updated();

      // Refresh our world
      GetParent()->Refresh();
      GetParent()->Update();
   }
}
示例#3
0
Size TopWindow::GetStdSize() const
{
	return GetMinSize();
}
示例#4
0
TextureGL::TextureGL(const TextureDescriptor &descriptor, const bool useCompressed) :
	Texture(descriptor)
{
	m_target = GLTextureType(descriptor.type);

	glGenTextures(1, &m_texture);
	glBindTexture(m_target, m_texture);
	CheckRenderErrors();


	// useCompressed is the global scope flag whereas descriptor.allowCompression is the local texture mode flag
	// either both or neither might be true however only compress the texture when both are true.
	const bool compressTexture = useCompressed && descriptor.allowCompression;

	switch (m_target) {
		case GL_TEXTURE_2D:
			if (!IsCompressed(descriptor.format)) {
				if (!descriptor.generateMipmaps)
					glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, 0);
				CheckRenderErrors();

				glTexImage2D(
					m_target, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				CheckRenderErrors();
				if (descriptor.generateMipmaps)
					glGenerateMipmap(m_target);
				CheckRenderErrors();
			} else {
				const GLint oglFormatMinSize = GetMinSize(descriptor.format);
				size_t Width = descriptor.dataSize.x;
				size_t Height = descriptor.dataSize.y;
				size_t bufSize = ((Width + 3) / 4) * ((Height + 3) / 4) * oglFormatMinSize;

				GLint maxMip = 0;
				for( unsigned int i=0; i < descriptor.numberOfMipMaps; ++i ) {
					maxMip = i;
					glCompressedTexImage2D(GL_TEXTURE_2D, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					if( Width<=MIN_COMPRESSED_TEXTURE_DIMENSION || Height<=MIN_COMPRESSED_TEXTURE_DIMENSION ) {
						break;
					}
					bufSize /= 4;
					Width /= 2;
					Height /= 2;
				}
				glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, maxMip);
				CheckRenderErrors();
			}
			break;

		case GL_TEXTURE_CUBE_MAP:
			if(!IsCompressed(descriptor.format)) {
				if(descriptor.generateMipmaps)
					glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, 0);
				CheckRenderErrors();

				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				glTexImage2D(
					GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, compressTexture ? GLCompressedInternalFormat(descriptor.format) : GLInternalFormat(descriptor.format),
					descriptor.dataSize.x, descriptor.dataSize.y, 0,
					GLImageFormat(descriptor.format),
					GLImageType(descriptor.format), 0);
				CheckRenderErrors();
				if (descriptor.generateMipmaps)
					glGenerateMipmap(m_target);
				CheckRenderErrors();
			} else {
				const GLint oglFormatMinSize = GetMinSize(descriptor.format);
				size_t Width = descriptor.dataSize.x;
				size_t Height = descriptor.dataSize.y;
				size_t bufSize = ((Width + 3) / 4) * ((Height + 3) / 4) * oglFormatMinSize;

				GLint maxMip = 0;
				for( unsigned int i=0; i < descriptor.numberOfMipMaps; ++i ) {
					maxMip = i;
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, i, GLInternalFormat(descriptor.format), Width, Height, 0, bufSize, 0);
					if( Width<=MIN_COMPRESSED_TEXTURE_DIMENSION || Height<=MIN_COMPRESSED_TEXTURE_DIMENSION ) {
						break;
					}
					bufSize /= 4;
					Width /= 2;
					Height /= 2;
				}
				glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, maxMip);
				CheckRenderErrors();
			}
			break;

		default:
			assert(0);
	}
	CheckRenderErrors();

	GLenum magFilter, minFilter, wrapS, wrapT;
	switch (descriptor.sampleMode) {
		default:	// safe default will fall through to LINEAR_CLAMP when run in release builds without assert
			assert(0);
		case LINEAR_CLAMP:
			magFilter = GL_LINEAR;
			minFilter = descriptor.generateMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
			wrapS = wrapT = GL_CLAMP_TO_EDGE;
			break;

		case NEAREST_CLAMP:
			magFilter = GL_NEAREST;
			minFilter = descriptor.generateMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
			wrapS = wrapT = GL_CLAMP_TO_EDGE;
			break;

		case LINEAR_REPEAT:
			magFilter = GL_LINEAR;
			minFilter = descriptor.generateMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
			wrapS = wrapT = GL_REPEAT;
			break;

		case NEAREST_REPEAT:
			magFilter = GL_NEAREST;
			minFilter = descriptor.generateMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
			wrapS = wrapT = GL_REPEAT;
			break;
	}

	glTexParameteri(m_target, GL_TEXTURE_WRAP_S, wrapS);
	glTexParameteri(m_target, GL_TEXTURE_WRAP_T, wrapS);
	glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, magFilter);
	glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, minFilter);
	CheckRenderErrors();

}
示例#5
0
文件: Static.cpp 项目: koz4k/soccer
Size ParentCtrl::GetStdSize() const
{
	return GetMinSize();
}
void CXTPDockingPaneSplitterContainer::_AdjustPanesLength(CXTPDockingPaneManager* pManager, CXTPDockingPaneBaseList& lst, CRect rect, BOOL bHoriz, BOOL bApply, int& nTotalLength, int& nLengthAvail)
{
	nTotalLength = 0;
	nLengthAvail = 0;

	CXTPDockingPaneBase* pClientPane = NULL;
	CXTPDockingPaneBase* pClient = pManager->GetClientPane();
	int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;

	POSITION pos = lst.GetHeadPosition();
	while (pos)
	{
		CXTPDockingPaneBase* pPane = lst.GetNext(pos);
		pPane->m_nLength = bHoriz ? pPane->m_szDocking.cx : pPane->m_szDocking.cy;

		MINMAXINFO mmi;
		pPane->GetMinMaxInfo(&mmi);
		pPane->m_nLength = max(GetMinSize(&mmi, bHoriz), min(GetMaxSize(&mmi, bHoriz), pPane->m_nLength));

		if (pClientPane == NULL && pPane->ContainPane(pClient))
		{
			if (!pManager->m_bHideClient || pPane->m_szDocking == CSize(0, 0))
			{
				pClientPane = pPane;
				if (bApply) pClientPane->m_szDocking = CSize(0, 0);
				pClientPane->m_nLength = 0;
			}
		}
		nTotalLength += pPane->m_nLength;
	}
	nLengthAvail = (bHoriz ? rect.Width() : rect.Height()) - (nSplitterSize * ((int)lst.GetCount() - 1));


	if (pClientPane && nTotalLength < nLengthAvail)
	{
		pClientPane->m_nLength = nLengthAvail - nTotalLength;
		if (bApply)
		{
			if (bHoriz) pClientPane->m_szDocking.cx = pClientPane->m_nLength;
			else pClientPane->m_szDocking.cy = pClientPane->m_nLength;
		}
		nTotalLength = nLengthAvail;
	}

	if (nLengthAvail > 0)
	{
		pos = lst.GetHeadPosition();
		while (pos)
		{
			CXTPDockingPaneBase* pPane = lst.GetNext(pos);

			if ((pPane->m_nLength < 0) || (nTotalLength == 0))
				continue;

			MINMAXINFO mmi;
			pPane->GetMinMaxInfo(&mmi);

			int nLength = pPane->m_nLength;

			if (nLengthAvail * nLength / nTotalLength < GetMinSize(&mmi, bHoriz))
				pPane->m_nLength = -GetMinSize(&mmi, bHoriz);
			else if (nLengthAvail * nLength / nTotalLength > GetMaxSize(&mmi, bHoriz))
				pPane->m_nLength = -GetMaxSize(&mmi, bHoriz);

			if (pPane->m_nLength < 0)
			{
				nLengthAvail += pPane->m_nLength;
				nTotalLength -= nLength;

				if (nLengthAvail < 0)
				{
					pPane->m_nLength -= nLengthAvail;
					nLengthAvail = 0;
					break;
				}

				pos = lst.GetHeadPosition();
			}
		}
	}
}
示例#7
0
文件: panel.cpp 项目: beanhome/dev
wxSize wxRibbonPanel::DoGetNextSmallerSize(wxOrientation direction,
        wxSize relative_to) const
{
    if(m_expanded_panel != NULL)
    {
        // Next size depends upon children, who are currently in the
        // expanded panel
        return m_expanded_panel->DoGetNextSmallerSize(direction, relative_to);
    }

    if(m_art != NULL)
    {
        wxClientDC dc((wxRibbonPanel*) this);
        wxSize child_relative = m_art->GetPanelClientSize(dc, this, relative_to, NULL);
        wxSize smaller(-1, -1);
        bool minimise = false;

        if(GetSizer())
        {
            // Get smallest non minimised size
            smaller = GetMinSize();
            // and adjust to child_relative for parent page
            if(m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL)
            {
                minimise = (child_relative.y <= smaller.y);
                if(smaller.x < child_relative.x)
                    smaller.x = child_relative.x;
            }
            else
            {
                minimise = (child_relative.x <= smaller.x);
                if(smaller.y < child_relative.y)
                    smaller.y = child_relative.y;
            }
        }
        else if(GetChildren().GetCount() == 1)
        {
            // Simple (and common) case of single ribbon child or Sizer
            wxWindow* child = GetChildren().Item(0)->GetData();
            wxRibbonControl* ribbon_child = wxDynamicCast(child, wxRibbonControl);
            if(ribbon_child != NULL)
            {
                smaller = ribbon_child->GetNextSmallerSize(direction, child_relative);
                minimise = (smaller == child_relative);
            }
        }

        if(minimise)
        {
            if(CanAutoMinimise())
            {
                wxSize minimised = m_minimised_size;
                switch(direction)
                {
                case wxHORIZONTAL:
                    minimised.SetHeight(relative_to.GetHeight());
                    break;
                case wxVERTICAL:
                    minimised.SetWidth(relative_to.GetWidth());
                    break;
                default:
                    break;
                }
                return minimised;
            }
            else
            {
                return relative_to;
            }
        }
        else if(smaller.IsFullySpecified()) // Use fallback if !(sizer/child = 1)
        {
            return m_art->GetPanelSize(dc, this, smaller, NULL);
        }
    }

    // Fallback: Decrease by 20% (or minimum size, whichever larger)
    wxSize current(relative_to);
    wxSize minimum(GetMinSize());
    if(direction & wxHORIZONTAL)
    {
        current.x = (current.x * 4) / 5;
        if(current.x < minimum.x)
        {
            current.x = minimum.x;
        }
    }
    if(direction & wxVERTICAL)
    {
        current.y = (current.y * 4) / 5;
        if(current.y < minimum.y)
        {
            current.y = minimum.y;
        }
    }
    return current;
}
示例#8
0
/**
 * Ok return our dimensions
 */
nsSize
nsImageBoxFrame::GetPrefSize(nsBoxLayoutState& aState)
{
  nsSize size(0,0);
  DISPLAY_PREF_SIZE(this, size);
  if (DoesNeedRecalc(mImageSize))
     GetImageSize();

  if (!mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0))
    size = nsSize(mSubRect.width, mSubRect.height);
  else
    size = mImageSize;

  nsSize intrinsicSize = size;

  nsMargin borderPadding(0,0,0,0);
  GetBorderAndPadding(borderPadding);
  size.width += borderPadding.LeftRight();
  size.height += borderPadding.TopBottom();

  bool widthSet, heightSet;
  nsIBox::AddCSSPrefSize(this, size, widthSet, heightSet);
  NS_ASSERTION(size.width != NS_INTRINSICSIZE && size.height != NS_INTRINSICSIZE,
               "non-intrinsic size expected");

  nsSize minSize = GetMinSize(aState);
  nsSize maxSize = GetMaxSize(aState);

  if (!widthSet && !heightSet) {
    if (minSize.width != NS_INTRINSICSIZE)
      minSize.width -= borderPadding.LeftRight();
    if (minSize.height != NS_INTRINSICSIZE)
      minSize.height -= borderPadding.TopBottom();
    if (maxSize.width != NS_INTRINSICSIZE)
      maxSize.width -= borderPadding.LeftRight();
    if (maxSize.height != NS_INTRINSICSIZE)
      maxSize.height -= borderPadding.TopBottom();

    size = nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(minSize.width, minSize.height,
                                                                 maxSize.width, maxSize.height,
                                                                 intrinsicSize.width, intrinsicSize.height);
    NS_ASSERTION(size.width != NS_INTRINSICSIZE && size.height != NS_INTRINSICSIZE,
                 "non-intrinsic size expected");
    size.width += borderPadding.LeftRight();
    size.height += borderPadding.TopBottom();
    return size;
  }

  if (!widthSet) {
    if (intrinsicSize.height > 0) {
      // Subtract off the border and padding from the height because the
      // content-box needs to be used to determine the ratio
      nscoord height = size.height - borderPadding.TopBottom();
      size.width = nscoord(PRInt64(height) * PRInt64(intrinsicSize.width) /
                           PRInt64(intrinsicSize.height));
    }
    else {
      size.width = intrinsicSize.width;
    }

    size.width += borderPadding.LeftRight();
  }
  else if (!heightSet) {
    if (intrinsicSize.width > 0) {
      nscoord width = size.width - borderPadding.LeftRight();
      size.height = nscoord(PRInt64(width) * PRInt64(intrinsicSize.height) /
                            PRInt64(intrinsicSize.width));
    }
    else {
      size.height = intrinsicSize.height;
    }

    size.height += borderPadding.TopBottom();
  }

  return BoundsCheck(minSize, size, maxSize);
}
示例#9
0
int DDSImage::GetMinDXTSize() const
{
	return GetMinSize(GetDXTFormat());
}
示例#10
0
/**
 * Adjust the size of sibling objects within the button.
 */
void MythUIType::SetMinAreaParent(MythRect actual_area, MythRect allowed_area,
                                  const MythUIType *calling_child)
{
    int delta_x = 0, delta_y = 0;
    MythRect area;

    // If a minsize is not set, don't use MinArea
    if (!m_MinSize.isValid())
        return;

    m_MinArea.setWidth(0);

    if (m_Area.width() < m_NormalSize.width())
        m_Area.setWidth(m_NormalSize.width());

    if (m_Area.height() < m_NormalSize.height())
        m_Area.setHeight(m_NormalSize.height());

    if (calling_child->m_Vanished)
    {
        actual_area.moveLeft(0);
        actual_area.moveTop(0);
        allowed_area.moveLeft(0);
        allowed_area.moveTop(0);
    }

    actual_area.translate(m_Area.topLeft());
    allowed_area.translate(m_Area.topLeft());

    QList<MythUIType *>::iterator it;

    for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
    {
        if (*it == calling_child || !(*it)->m_Initiator)
            continue;

        // Find union of area(s)
        area = (*it)->GetArea();
        area.translate(m_Area.topLeft());
        actual_area = actual_area.united(area);

        area = (*it)->m_Area;
        area.translate(m_Area.topLeft());
        allowed_area = allowed_area.united(area);
    }

    // Make sure it is not larger than the area allowed
    actual_area = actual_area.intersected(m_Area);
    allowed_area = allowed_area.intersected(m_Area);

    if (m_Vanish && actual_area.size().isNull())
    {
        m_Vanished = true;
    }
    else
    {
        if (calling_child->m_Vanished)
        {
            delta_x = (actual_area.x() + actual_area.width()) -
                      (m_Area.x() + m_Area.width());
            delta_y = (actual_area.y() + actual_area.height()) -
                      (m_Area.y() + m_Area.height());
        }
        else
        {
            delta_x = (actual_area.x() + actual_area.width()) -
                      (allowed_area.x() + allowed_area.width());
            delta_y = (actual_area.y() + actual_area.height()) -
                      (allowed_area.y() + allowed_area.height());
        }

        m_Vanished = false;
    }

    for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
    {
        if (*it == calling_child)
            continue;

        if (!(*it)->m_Initiator)
        {
            if (m_Vanished)
                (*it)->VanishSibling();
            else
                (*it)->AdjustMinArea(delta_x, delta_y);
        }

        area = (*it)->GetArea();
        area.translate(m_Area.topLeft());
        actual_area = actual_area.united(area);
    }

    QSize bound(actual_area.width(), actual_area.height());

    if (m_Vanished)
    {
        m_MinArea.moveLeft(0);
        m_MinArea.moveTop(0);
    }
    else
        bound = bound.expandedTo(GetMinSize());

    m_MinArea.setWidth(bound.width());
    m_MinArea.setHeight(bound.height());

    if (m_Parent)
        m_Parent->SetMinAreaParent(actual_area, m_Area, this);
}
示例#11
0
void EffectRack::Add(Effect *effect, bool active, bool favorite)
{
   if (mEffects.Index(effect) != wxNOT_FOUND)
   {
      return;
   }

   wxBitmapButton *bb;
 
   wxASSERT(mPanel); // To justify safenew
   bb = safenew wxBitmapButton(mPanel, ID_POWER + mNumEffects, mPowerRaised);
   bb->SetBitmapSelected(mPowerRaised);
   bb->SetName(_("Active State"));
   bb->SetToolTip(_("Set effect active state"));
   mPowerState.Add(active);
   if (active)
   {
      bb->SetBitmapLabel(mPowerPushed);
      bb->SetBitmapSelected(mPowerPushed);
   }
   else
   {
      bb->SetBitmapLabel(mPowerRaised);
      bb->SetBitmapSelected(mPowerRaised);
   }
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   bb = safenew wxBitmapButton(mPanel, ID_EDITOR + mNumEffects, mSettingsRaised);
   bb->SetBitmapSelected(mSettingsPushed);
   bb->SetName(_("Show/Hide Editor"));
   bb->SetToolTip(_("Open/close effect editor"));
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   bb = safenew wxBitmapButton(mPanel, ID_UP + mNumEffects, mUpRaised);
   bb->SetBitmapSelected(mUpPushed);
   bb->SetBitmapDisabled(mUpDisabled);
   bb->SetName(_("Move Up"));
   bb->SetToolTip(_("Move effect up in the rack"));
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   bb = safenew wxBitmapButton(mPanel, ID_DOWN + mNumEffects, mDownRaised);
   bb->SetBitmapSelected(mDownPushed);
   bb->SetBitmapDisabled(mDownDisabled);
   bb->SetName(_("Move Down"));
   bb->SetToolTip(_("Move effect down in the rack"));
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   bb = safenew wxBitmapButton(mPanel, ID_FAV + mNumEffects, mFavRaised);
   bb->SetBitmapSelected(mFavPushed);
   bb->SetName(_("Favorite"));
   bb->SetToolTip(_("Mark effect as a favorite"));
   mFavState.Add(favorite);
   if (favorite)
   {
      bb->SetBitmapLabel(mFavPushed);
      bb->SetBitmapSelected(mFavPushed);
   }
   else
   {
      bb->SetBitmapLabel(mFavRaised);
      bb->SetBitmapSelected(mFavRaised);
   }
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   bb = safenew wxBitmapButton(mPanel, ID_REMOVE + mNumEffects, mRemoveRaised);
   bb->SetBitmapSelected(mRemovePushed);
   bb->SetName(_("Remove"));
   bb->SetToolTip(_("Remove effect from the rack"));
   mMainSizer->Add(bb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);

   wxStaticText *text = safenew wxStaticText(mPanel, ID_NAME + mNumEffects, effect->GetName());
   text->SetToolTip(_("Name of the effect"));
   mMainSizer->Add(text, 0, wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5);

   mMainSizer->Layout();
   SetSize(GetMinSize());
   Fit();
   Update();

   mEffects.Add(effect);
   mNumEffects++;

   if (!mTimer.IsRunning())
   {
      mTimer.Start(1000);
   }

   if (active)
   {
      UpdateActive();
   }
}
示例#12
0
// -----------------------------------------------------------------------------
// Sets up the dialog UI layout
// -----------------------------------------------------------------------------
void GfxConvDialog::setupLayout()
{
	int px_inner        = UI::pad();
	int px_outer        = UI::padLarge();
	int px_pad          = UI::px(UI::Size::PadMinimum);
	int px_preview_size = UI::scalePx(192);

	auto msizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(msizer);

	auto m_vbox = new wxBoxSizer(wxVERTICAL);
	msizer->Add(m_vbox, 1, wxEXPAND | wxALL, px_outer);

	// Add current format label
	label_current_format_ = new wxStaticText(this, -1, "Current Format:");
	m_vbox->Add(label_current_format_, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, px_inner);

	// Add 'Convert To' combo box
	auto hbox = new wxBoxSizer(wxHORIZONTAL);
	m_vbox->Add(hbox, 0, wxEXPAND | wxBOTTOM, px_outer);
	hbox->Add(new wxStaticText(this, -1, "Convert to:"), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, px_pad);
	combo_target_format_ = new wxChoice(this, -1);
	hbox->Add(combo_target_format_, 1, wxEXPAND);


	// Add Gfx previews
	auto frame      = new wxStaticBox(this, -1, "Colour Options");
	auto framesizer = new wxStaticBoxSizer(frame, wxHORIZONTAL);
	m_vbox->Add(framesizer, 1, wxEXPAND | wxBOTTOM, px_outer);

	auto gbsizer = new wxGridBagSizer(px_inner, px_inner);
	framesizer->Add(gbsizer, 1, wxEXPAND | wxALL, px_inner);

	// Current
	gbsizer->Add(new wxStaticText(this, -1, "Current Graphic"), { 0, 0 }, { 1, 1 });
	gfx_current_ = new GfxCanvas(this, -1);
	gfx_current_->SetInitialSize(wxSize(px_preview_size, px_preview_size));
	gfx_current_->setViewType(GfxCanvas::View::Centered);
	gbsizer->Add(gfx_current_, { 1, 0 }, { 1, 1 }, wxEXPAND);
	pal_chooser_current_ = new PaletteChooser(this, -1);
	pal_chooser_current_->selectPalette(current_palette_name_);
	gbsizer->Add(pal_chooser_current_, { 2, 0 }, { 1, 1 }, wxEXPAND);

	// Converted
	gbsizer->Add(new wxStaticText(this, -1, "Converted Graphic"), { 0, 1 }, { 1, 2 });
	gfx_target_ = new GfxCanvas(this, -1);
	gfx_target_->SetInitialSize(wxSize(px_preview_size, px_preview_size));
	gfx_target_->setViewType(GfxCanvas::View::Centered);
	gbsizer->Add(gfx_target_, { 1, 1 }, { 1, 2 }, wxEXPAND);
	pal_chooser_target_ = new PaletteChooser(this, -1);
	pal_chooser_target_->selectPalette(target_palette_name_);
	gbsizer->Add(pal_chooser_target_, { 2, 1 }, { 1, 1 }, wxEXPAND);
	btn_colorimetry_settings_ =
		new wxBitmapButton(this, -1, Icons::getIcon(Icons::General, "settings"), wxDefaultPosition, wxDefaultSize);
	btn_colorimetry_settings_->SetToolTip("Adjust Colorimetry Settings...");
	gbsizer->Add(btn_colorimetry_settings_, { 2, 2 }, { 1, 1 }, wxALIGN_CENTER);
	gbsizer->AddGrowableCol(0, 1);
	gbsizer->AddGrowableCol(1, 1);
	gbsizer->AddGrowableRow(1, 1);


	// Add transparency options
	frame      = new wxStaticBox(this, -1, "Transparency Options");
	framesizer = new wxStaticBoxSizer(frame, wxVERTICAL);
	m_vbox->Add(framesizer, 0, wxEXPAND | wxBOTTOM, px_outer);

	gbsizer = new wxGridBagSizer(px_inner, px_inner);
	framesizer->Add(gbsizer, 1, wxEXPAND | wxALL, px_inner);

	// 'Enable transparency' checkbox
	cb_enable_transparency_ = new wxCheckBox(this, -1, "Enable Transparency");
	cb_enable_transparency_->SetValue(true);
	cb_enable_transparency_->SetToolTip("Uncheck this to remove any existing transparency from the graphic");
	gbsizer->Add(cb_enable_transparency_, { 0, 0 }, { 1, 2 });

	// Keep existing transparency
	rb_transparency_existing_ =
		new wxRadioButton(this, 100, "Existing w/Threshold:", wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
	rb_transparency_existing_->SetValue(true);
	gbsizer->Add(rb_transparency_existing_, { 1, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL);

	// Alpha threshold
	slider_alpha_threshold_ = new wxSlider(
		this, -1, 0, 0, 255, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_LABELS | wxSL_BOTTOM);
	slider_alpha_threshold_->SetToolTip(
		"Specifies the 'cutoff' transparency level, anything above this will be fully opaque, "
		"anything equal or below will be completely transparent");
	gbsizer->Add(slider_alpha_threshold_, { 1, 1 }, { 1, 1 }, wxEXPAND);

	// Transparent colour
	rb_transparency_colour_ = new wxRadioButton(this, 101, "Transparent Colour:", wxDefaultPosition, wxDefaultSize, 0);
	rb_transparency_colour_->SetValue(false);
	gbsizer->Add(rb_transparency_colour_, { 2, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL);

	colbox_transparent_ = new ColourBox(this, -1, false);
	colbox_transparent_->setColour(ColRGBA(0, 255, 255, 255));
	gbsizer->Add(colbox_transparent_, { 2, 1 }, { 1, 1 });

	// From brightness
	rb_transparency_brightness_ = new wxRadioButton(this, 102, "Transparency from Brightness");
	rb_transparency_brightness_->SetValue(false);
	gbsizer->Add(rb_transparency_brightness_, { 3, 0 }, { 1, 2 });
	gbsizer->AddGrowableCol(1, 1);

	// Buttons
	hbox = new wxBoxSizer(wxHORIZONTAL);
	m_vbox->Add(hbox, 0, wxEXPAND);

	btn_convert_     = new wxButton(this, -1, "Convert");
	btn_convert_all_ = new wxButton(this, -1, "Convert All");
	btn_skip_        = new wxButton(this, -1, "Skip");
	btn_skip_all_    = new wxButton(this, -1, "Skip All");

	hbox->AddStretchSpacer(1);
	hbox->Add(btn_convert_, 0, wxEXPAND | wxRIGHT, px_inner);
	hbox->Add(btn_convert_all_, 0, wxEXPAND | wxRIGHT, px_inner);
	hbox->Add(btn_skip_, 0, wxEXPAND | wxRIGHT, px_inner);
	hbox->Add(btn_skip_all_, 0, wxEXPAND);


	// Bind events
	Bind(wxEVT_SIZE, &GfxConvDialog::onResize, this);
	btn_convert_->Bind(wxEVT_BUTTON, &GfxConvDialog::onBtnConvert, this);
	btn_convert_all_->Bind(wxEVT_BUTTON, &GfxConvDialog::onBtnConvertAll, this);
	btn_skip_->Bind(wxEVT_BUTTON, &GfxConvDialog::onBtnSkip, this);
	btn_skip_all_->Bind(wxEVT_BUTTON, &GfxConvDialog::onBtnSkipAll, this);
	combo_target_format_->Bind(wxEVT_CHOICE, &GfxConvDialog::onTargetFormatChanged, this);
	pal_chooser_current_->Bind(wxEVT_CHOICE, &GfxConvDialog::onCurrentPaletteChanged, this);
	pal_chooser_target_->Bind(wxEVT_CHOICE, &GfxConvDialog::onTargetPaletteChanged, this);
	slider_alpha_threshold_->Bind(wxEVT_SLIDER, &GfxConvDialog::onAlphaThresholdChanged, this);
	cb_enable_transparency_->Bind(wxEVT_CHECKBOX, &GfxConvDialog::onEnableTransparencyChanged, this);
	rb_transparency_colour_->Bind(wxEVT_RADIOBUTTON, &GfxConvDialog::onTransTypeChanged, this);
	rb_transparency_existing_->Bind(wxEVT_RADIOBUTTON, &GfxConvDialog::onTransTypeChanged, this);
	rb_transparency_brightness_->Bind(wxEVT_RADIOBUTTON, &GfxConvDialog::onTransTypeChanged, this);
	Bind(wxEVT_COLOURBOX_CHANGED, &GfxConvDialog::onTransColourChanged, this, colbox_transparent_->GetId());
	gfx_current_->Bind(wxEVT_LEFT_DOWN, &GfxConvDialog::onPreviewCurrentMouseDown, this);
	btn_colorimetry_settings_->Bind(wxEVT_BUTTON, &GfxConvDialog::onBtnColorimetrySettings, this);


	// Autosize to fit contents (and set this as the minimum size)
	SetMinClientSize(msizer->GetMinSize());
}
示例#13
0
NS_IMETHODIMP
nsLeafBoxFrame::Reflow(nsPresContext*   aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus)
{
  // This is mostly a copy of nsBoxFrame::Reflow().
  // We aren't able to share an implementation because of the frame
  // class hierarchy.  If you make changes here, please keep
  // nsBoxFrame::Reflow in sync.

  DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame", aReflowState.reason);
  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);

  NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0");

#ifdef DO_NOISY_REFLOW
  printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
  printf("%p ** nsLBF::Reflow %d R: ", this, myCounter++);
  switch (aReflowState.reason) {
    case eReflowReason_Initial:
      printf("Ini");break;
    case eReflowReason_Incremental:
      printf("Inc");break;
    case eReflowReason_Resize:
      printf("Rsz");break;
    case eReflowReason_StyleChange:
      printf("Sty");break;
    case eReflowReason_Dirty:
      printf("Drt ");
      break;
    default:printf("<unknown>%d", aReflowState.reason);break;
  }
  
  printSize("AW", aReflowState.availableWidth);
  printSize("AH", aReflowState.availableHeight);
  printSize("CW", aReflowState.mComputedWidth);
  printSize("CH", aReflowState.mComputedHeight);

  printf(" *\n");

#endif

  aStatus = NS_FRAME_COMPLETE;

  // create the layout state
  nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize);

  // coelesce reflows if we are root.
  state.HandleReflow(this);
  
  nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight);

  nsMargin m;
  m = aReflowState.mComputedBorderPadding;

  //GetBorderAndPadding(m);

  // this happens sometimes. So lets handle it gracefully.
  if (aReflowState.mComputedHeight == 0) {
    nsSize minSize(0,0);
    GetMinSize(state, minSize);
    computedSize.height = minSize.height - m.top - m.bottom;
  }

  nsSize prefSize(0,0);

  // if we are told to layout intrinic then get our preferred size.
  if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
     nsSize minSize(0,0);
     nsSize maxSize(0,0);
     GetPrefSize(state, prefSize);
     GetMinSize(state,  minSize);
     GetMaxSize(state,  maxSize);
     BoundsCheck(minSize, prefSize, maxSize);
  }

  // get our desiredSize
  if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) {
    computedSize.width = prefSize.width;
  } else {
    computedSize.width += m.left + m.right;
  }

  if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) {
    computedSize.height = prefSize.height;
  } else {
    computedSize.height += m.top + m.bottom;
  }

  // handle reflow state min and max sizes

  if (computedSize.width > aReflowState.mComputedMaxWidth)
    computedSize.width = aReflowState.mComputedMaxWidth;

  if (computedSize.height > aReflowState.mComputedMaxHeight)
    computedSize.height = aReflowState.mComputedMaxHeight;

  if (computedSize.width < aReflowState.mComputedMinWidth)
    computedSize.width = aReflowState.mComputedMinWidth;

  if (computedSize.height < aReflowState.mComputedMinHeight)
    computedSize.height = aReflowState.mComputedMinHeight;

  nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);

  SetBounds(state, r);
 
  // layout our children
  Layout(state);
  
  // ok our child could have gotten bigger. So lets get its bounds
  
  // get the ascent
  nscoord ascent = mRect.height;

  // Only call GetAscent when not doing Initial reflow while in PP
  // or when it is Initial reflow while in PP and a chrome doc
  // If called again with initial reflow it crashes because the 
  // frames are fully constructed (I think).
  PRBool isChrome;
  PRBool isInitialPP = nsBoxFrame::IsInitialReflowForPrintPreview(state, isChrome);
  if (!isInitialPP || (isInitialPP && isChrome)) {
    GetAscent(state, ascent);
  }

  aDesiredSize.width  = mRect.width;
  aDesiredSize.height = mRect.height;
  aDesiredSize.ascent = ascent;
  aDesiredSize.descent = 0;

  // NS_FRAME_OUTSIDE_CHILDREN is set in SetBounds() above
  if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
    nsRect* overflowArea = GetOverflowAreaProperty();
    NS_ASSERTION(overflowArea, "Failed to set overflow area property");
    aDesiredSize.mOverflowArea = *overflowArea;
  }

  // max sure the max element size reflects
  // our min width
  nscoord* maxElementWidth = state.GetMaxElementWidth();
  if (maxElementWidth)
  {
     nsSize minSize(0,0);
     GetMinSize(state,  minSize);

     if (mRect.width > minSize.width) {
       if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) {
         *maxElementWidth = minSize.width;
       } else {
         *maxElementWidth = mRect.width;
       }
     } else {
        *maxElementWidth = mRect.width;
     }
  }
#ifdef DO_NOISY_REFLOW
  {
    printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);

    if (maxElementWidth) {
      printf("MW:%d\n", *maxElementWidth); 
    } else {
      printf("MW:?\n"); 
    }

  }
#endif

  return NS_OK;
}
示例#14
0
NS_IMETHODIMP
nsLeafBoxFrame::Reflow(nsPresContext*   aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus)
{
  // This is mostly a copy of nsBoxFrame::Reflow().
  // We aren't able to share an implementation because of the frame
  // class hierarchy.  If you make changes here, please keep
  // nsBoxFrame::Reflow in sync.

  DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);

  NS_ASSERTION(aReflowState.ComputedWidth() >=0 &&
               aReflowState.ComputedHeight() >= 0, "Computed Size < 0");

#ifdef DO_NOISY_REFLOW
  printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
  printf("%p ** nsLBF::Reflow %d R: ", this, myCounter++);
  switch (aReflowState.reason) {
    case eReflowReason_Initial:
      printf("Ini");break;
    case eReflowReason_Incremental:
      printf("Inc");break;
    case eReflowReason_Resize:
      printf("Rsz");break;
    case eReflowReason_StyleChange:
      printf("Sty");break;
    case eReflowReason_Dirty:
      printf("Drt ");
      break;
    default:printf("<unknown>%d", aReflowState.reason);break;
  }
  
  printSize("AW", aReflowState.availableWidth);
  printSize("AH", aReflowState.availableHeight);
  printSize("CW", aReflowState.ComputedWidth());
  printSize("CH", aReflowState.ComputedHeight());

  printf(" *\n");

#endif

  aStatus = NS_FRAME_COMPLETE;

  // create the layout state
  nsBoxLayoutState state(aPresContext, aReflowState.rendContext);

  nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight());

  nsMargin m;
  m = aReflowState.mComputedBorderPadding;

  //GetBorderAndPadding(m);

  // this happens sometimes. So lets handle it gracefully.
  if (aReflowState.ComputedHeight() == 0) {
    nsSize minSize = GetMinSize(state);
    computedSize.height = minSize.height - m.top - m.bottom;
  }

  nsSize prefSize(0,0);

  // if we are told to layout intrinic then get our preferred size.
  if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
     prefSize = GetPrefSize(state);
     nsSize minSize = GetMinSize(state);
     nsSize maxSize = GetMaxSize(state);
     prefSize = BoundsCheck(minSize, prefSize, maxSize);
  }

  // get our desiredSize
  if (aReflowState.ComputedWidth() == NS_INTRINSICSIZE) {
    computedSize.width = prefSize.width;
  } else {
    computedSize.width += m.left + m.right;
  }

  if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
    computedSize.height = prefSize.height;
  } else {
    computedSize.height += m.top + m.bottom;
  }

  // handle reflow state min and max sizes
  // XXXbz the width handling here seems to be wrong, since
  // mComputedMin/MaxWidth is a content-box size, whole
  // computedSize.width is a border-box size...
  if (computedSize.width > aReflowState.mComputedMaxWidth)
    computedSize.width = aReflowState.mComputedMaxWidth;

  if (computedSize.width < aReflowState.mComputedMinWidth)
    computedSize.width = aReflowState.mComputedMinWidth;

  // Now adjust computedSize.height for our min and max computed
  // height.  The only problem is that those are content-box sizes,
  // while computedSize.height is a border-box size.  So subtract off
  // m.TopBottom() before adjusting, then readd it.
  computedSize.height = std::max(0, computedSize.height - m.TopBottom());
  computedSize.height = NS_CSS_MINMAX(computedSize.height,
                                      aReflowState.mComputedMinHeight,
                                      aReflowState.mComputedMaxHeight);
  computedSize.height += m.TopBottom();

  nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);

  SetBounds(state, r);
 
  // layout our children
  Layout(state);
  
  // ok our child could have gotten bigger. So lets get its bounds
  aDesiredSize.width  = mRect.width;
  aDesiredSize.height = mRect.height;
  aDesiredSize.ascent = GetBoxAscent(state);

  // the overflow rect is set in SetBounds() above
  aDesiredSize.mOverflowAreas = GetOverflowAreas();

#ifdef DO_NOISY_REFLOW
  {
    printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);

    if (maxElementWidth) {
      printf("MW:%d\n", *maxElementWidth); 
    } else {
      printf("MW:?\n"); 
    }

  }
#endif

  return NS_OK;
}
示例#15
0
wxSize wxRibbonToolBar::DoGetBestSize() const
{
    return GetMinSize();
}
示例#16
0
SettingsFrame::SettingsFrame(CreatorFrame* parent, trance_pb::System& system)
: wxFrame{parent,
          wxID_ANY,
          "System settings",
          wxDefaultPosition,
          wxDefaultSize,
          wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN}
, _system{system}
, _parent{parent}
{
  auto panel = new wxPanel{this};
  auto sizer = new wxBoxSizer{wxVERTICAL};
  auto top = new wxBoxSizer{wxHORIZONTAL};
  auto bottom = new wxBoxSizer{wxHORIZONTAL};
  auto left = new wxStaticBoxSizer{wxVERTICAL, panel, "Memory"};
  auto right = new wxStaticBoxSizer{wxVERTICAL, panel, "Rendering"};
  auto right_mode = new wxBoxSizer{wxHORIZONTAL};

  _monitor =
      new wxRadioButton{panel, wxID_ANY, "Monitor", wxDefaultPosition, wxDefaultSize, wxRB_GROUP};
  _oculus = new wxRadioButton{panel, wxID_ANY, "Oculus Rift"};
  _openvr = new wxRadioButton{panel, wxID_ANY, "SteamVR"};

  _enable_vsync = new wxCheckBox{panel, wxID_ANY, "Enable VSync"};
  _image_cache_size = new wxSpinCtrl{panel, wxID_ANY};
  _animation_buffer_size = new wxSpinCtrl{panel, wxID_ANY};
  _font_cache_size = new wxSpinCtrl{panel, wxID_ANY};
  _draw_depth = new wxSlider{panel,
                             wxID_ANY,
                             f2v(_system.draw_depth().draw_depth()),
                             0,
                             8,
                             wxDefaultPosition,
                             wxDefaultSize,
                             wxSL_HORIZONTAL | wxSL_AUTOTICKS | wxSL_VALUE_LABEL};
  _eye_spacing = new wxSpinCtrlDouble{panel, wxID_ANY};
  auto button_ok = new wxButton{panel, wxID_ANY, "OK"};
  auto button_cancel = new wxButton{panel, wxID_ANY, "Cancel"};
  _button_apply = new wxButton{panel, wxID_ANY, "Apply"};

  _monitor->SetToolTip(MONITOR_TOOLTIP);
  _oculus->SetToolTip(OCULUS_TOOLTIP);
  _openvr->SetToolTip(OPENVR_TOOLTIP);
  if (system.renderer() == trance_pb::System::OPENVR) {
    _openvr->SetValue(true);
  } else if (system.renderer() == trance_pb::System::OCULUS) {
    _oculus->SetValue(true);
  } else {
    _monitor->SetValue(true);
    _eye_spacing->Disable();
  }
  _enable_vsync->SetToolTip(VSYNC_TOOLTIP);
  _enable_vsync->SetValue(_system.enable_vsync());
  _image_cache_size->SetToolTip(IMAGE_CACHE_SIZE_TOOLTIP);
  _image_cache_size->SetRange(16, 1024);
  _image_cache_size->SetValue(_system.image_cache_size());
  _animation_buffer_size->SetToolTip(ANIMATION_BUFFER_SIZE_TOOLTIP);
  _animation_buffer_size->SetRange(8, 512);
  _animation_buffer_size->SetValue(_system.animation_buffer_size());
  _font_cache_size->SetToolTip(FONT_CACHE_SIZE_TOOLTIP);
  _font_cache_size->SetRange(2, 256);
  _font_cache_size->SetValue(_system.font_cache_size());
  _draw_depth->SetToolTip(DRAW_DEPTH_TOOLTIP);
  _eye_spacing->SetToolTip(EYE_SPACING_TOOLTIP);
  _eye_spacing->SetRange(-1., 1.);
  _eye_spacing->SetIncrement(1. / 128);
  _eye_spacing->SetValue(_system.eye_spacing().eye_spacing());

  sizer->Add(top, 1, wxEXPAND, 0);
  sizer->Add(bottom, 0, wxEXPAND, 0);
  top->Add(left, 1, wxALL | wxEXPAND, DEFAULT_BORDER);
  top->Add(right, 1, wxALL | wxEXPAND, DEFAULT_BORDER);

  wxStaticText* label = nullptr;
  label = new wxStaticText{panel, wxID_ANY, "Image cache size:"};
  label->SetToolTip(IMAGE_CACHE_SIZE_TOOLTIP);
  left->Add(label, 0, wxALL, DEFAULT_BORDER);
  left->Add(_image_cache_size, 0, wxALL | wxEXPAND, DEFAULT_BORDER);
  label = new wxStaticText{panel, wxID_ANY, "Animation buffer size:"};
  label->SetToolTip(ANIMATION_BUFFER_SIZE_TOOLTIP);
  left->Add(label, 0, wxALL, DEFAULT_BORDER);
  left->Add(_animation_buffer_size, 0, wxALL | wxEXPAND, DEFAULT_BORDER);
  label = new wxStaticText{panel, wxID_ANY, "Font cache size:"};
  label->SetToolTip(IMAGE_CACHE_SIZE_TOOLTIP);
  left->Add(label, 0, wxALL, DEFAULT_BORDER);
  left->Add(_font_cache_size, 0, wxALL | wxEXPAND, DEFAULT_BORDER);
  label = new wxStaticText{panel, wxID_ANY, "Rendering mode:"};
  right->Add(right_mode, 0, wxALL | wxEXPAND, DEFAULT_BORDER);
  right_mode->Add(_monitor, 1, wxALL, DEFAULT_BORDER);
  right_mode->Add(_oculus, 1, wxALL, DEFAULT_BORDER);
  right_mode->Add(_openvr, 1, wxALL, DEFAULT_BORDER);
  right->Add(_enable_vsync, 0, wxALL, DEFAULT_BORDER);
  label = new wxStaticText{panel, wxID_ANY, "Draw depth:"};
  label->SetToolTip(DRAW_DEPTH_TOOLTIP);
  right->Add(label, 0, wxALL, DEFAULT_BORDER);
  right->Add(_draw_depth, 0, wxALL | wxEXPAND, DEFAULT_BORDER);
  _eye_spacing_label = new wxStaticText{panel, wxID_ANY, "Eye spacing (in VR):"};
  _eye_spacing_label->SetToolTip(EYE_SPACING_TOOLTIP);
  right->Add(_eye_spacing_label, 0, wxALL, DEFAULT_BORDER);
  right->Add(_eye_spacing, 0, wxALL | wxEXPAND, DEFAULT_BORDER);

  bottom->Add(button_ok, 1, wxALL, DEFAULT_BORDER);
  bottom->Add(button_cancel, 1, wxALL, DEFAULT_BORDER);
  bottom->Add(_button_apply, 1, wxALL, DEFAULT_BORDER);

  _eye_spacing_label->Enable(!_monitor->GetValue());
  _eye_spacing->Enable(!_monitor->GetValue());
  _button_apply->Enable(false);

  panel->SetSizer(sizer);
  SetClientSize(sizer->GetMinSize());
  CentreOnParent();
  Show(true);

  auto changed = [&](wxCommandEvent&) { Changed(); };
  Bind(wxEVT_RADIOBUTTON, changed);
  Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, changed);
  Bind(wxEVT_SLIDER, changed);
  Bind(wxEVT_SPINCTRL, changed);
  Bind(wxEVT_SPINCTRLDOUBLE, changed);

  button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) {
    Apply();
    Close();
  });
  button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) { Close(); });
  _button_apply->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent&) { Apply(); });

  Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent& event) {
    _parent->SettingsClosed();
    Destroy();
  });
}