3

If you run the AdvanceDemo in the JVCL's JvDocking example code, with VSNetStyle selected, you can drag a second form onto the main form; a tab with the second form's title will be displayed. If you then drag a another form onto the same side of the main form, another tab will be created. The two tabs will overlap:

screenshot of overlapping tabs

Is there a way to control how much these two tabs overlap? I'd like the tabs to be separated enough so that users can read the text on both tabs.

Thanks, as always -- Al C.

Al C
  • 4,551
  • 5
  • 35
  • 63
  • I think which you will get answers to this question, if you include a image of the task which you want accomplish. – RRUZ Jul 08 '11 at 21:24
  • Happy to do so ... if you'll tell me how :-) – Al C Jul 08 '11 at 21:26
  • http://meta.stackexchange.com/questions/75491/how-to-upload-an-image-to-a-post – RRUZ Jul 08 '11 at 21:32
  • I would say this is a bug - there seems to be enough room for both tabs yet the top one barely shows... I suggest you to discuss it with JVCL people in their "jedi.jvcl" NNTP newsgroup at hermes.grizzlydev.com. – ain Jul 09 '11 at 07:42

1 Answers1

5

As ain commented, I also think it is a bug. More precisely a bug in TJvDockVSChannel.Paint which draws the tabs (internally the tabs are called blocks). Such a block has a protected property InactiveBlockWidth whose name suggest controlling its width. The property works fine for the tab itself, but the caption is shifted by that same amount again in TJvDockVSChannel.Paint, which seems to me to be the problem.

You can experiment as follows, by assigning the OnFinishSetDockPanelSize event of the DockServer:

type
  TJvDockVSBlockAccess = class(TJvDockVSBlock);

procedure TMainForm.lbDockServer1FinishSetDockPanelSize(
  DockPanel: TJvDockPanel);
var
  Channel: TJvDockVSChannel;
  Block: TJvDockVSBlockAccess;
  i: Integer;
begin
  if DockPanel is TJvDockVSNETPanel then
  begin
    Channel := TJvDockVSNETPanel(DockPanel).VSChannel;
    for i := 0 to Channel.BlockCount - 1 do
    begin
      Block := TJvDockVSBlockAccess(Channel.Block[i]);
      Block.InactiveBlockWidth := 100;
    end;
  end;
end;

Since this is a protected property for now, it might indicate its functionality being under construction. I suppose Jedi's dev team have decided for now to draw only the glyph of each inactive tab, because there lacks a full implementation for dynamic handling of the tab widths. E.g. you should be able to set a minimum width of each tab, and when the bar (i.e. the container in which it resides) changes height, all tabs should widen or narrow accordingly.

Edit:

Thanks to the flexible design, you can work around the bug by setting the DockPanelClass property of the DockServer. I suppose that property has to be set befóre setting the Style property. It involves rewriting the whole Paint routine, because InactiveBlockWidth is also used in GetBlockRect, which in turn is not virtual:

type
  TJvDockVSBlockAccess = class(TJvDockVSBlock);

  THackJvDockVSNETPanel = class(TJvDockVSNETPanel)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  THackJvDockVSChannel = class(TJvDockVSChannel)
  protected
    procedure Paint; override;
    procedure ResetBlock; override;
    procedure Resize; override;
  end;

const
  InactiveTabWidth = 100;

{ TMainForm }

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ...
  JvDockVSNetStyle1.DockPanelClass := THackJvDockVSNETPanel;
end;

{ THackJvDockVSNETPanel }

constructor THackJvDockVSNETPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  VSChannelClass := THackJvDockVSChannel;
end;

{ THackJvDockVSChannel }

procedure THackJvDockVSChannel.Paint;
var
  I: Integer;

  procedure DrawSingleBlock(Block: TJvDockVSBlockAccess);
  var
    DrawRect: TRect;
    I: Integer;
    OldGraphicsMode: Integer;
    VisiblePaneCount: Integer;

    procedure AdjustImagePos;
    begin
      if Align = alLeft then
      begin
        Inc(DrawRect.Left, 3);
        Inc(DrawRect.Top, 4);
      end
      else if Align = alTop then
      begin
        Inc(DrawRect.Left, 4);
        Inc(DrawRect.Top, 2);
      end
      else if Align = alRight then
      begin
        Inc(DrawRect.Left, 4);
        Inc(DrawRect.Top, 4);
      end
      else if Align = alBottom then
      begin
        Inc(DrawRect.Left, 4);
        Inc(DrawRect.Top, 3);
      end;
    end;

  begin
    VisiblePaneCount := 0;
    for I := 0 to Block.VSPaneCount - 1 do
    begin
      if not Block.VSPane[I].Visible then
        Continue;
      GetBlockRect(Block, I, DrawRect);
      Canvas.Brush.Color := TabColor;
      Canvas.FillRect(DrawRect);
      Canvas.Brush.Color := clGray;
      Canvas.FrameRect(DrawRect);
      AdjustImagePos;
      Block.ImageList.Draw(Canvas, DrawRect.Left, DrawRect.Top, I);
      if Align in [alTop, alBottom] then
        Inc(DrawRect.Left, 24)
      else if Align in [alLeft, alRight] then
      begin
        Inc(DrawRect.Top, 24);
        if Align = alLeft then
          DrawRect.Left := 15
        else
          DrawRect.Left := 20;
        DrawRect.Right := DrawRect.Left + (DrawRect.Bottom - DrawRect.Top);
      end;
      Canvas.Brush.Color := TabColor;
      Canvas.Pen.Color := clBlack;
      Dec(DrawRect.Right, 3);
      OldGraphicsMode := SetGraphicsMode(Canvas.Handle, GM_ADVANCED);
      Canvas.Brush.Style := bsClear;
      DrawText(Canvas.Handle, PChar(Block.VSPane[I].DockForm.Caption), -1,
        DrawRect, DT_END_ELLIPSIS or DT_NOCLIP);
      SetGraphicsMode(Canvas.Handle, OldGraphicsMode);
      Inc(VisiblePaneCount);
    end;
    if VisiblePaneCount > 0 then
      CurrentPos := CurrentPos + BlockInterval;
  end;

begin
  ResetBlock;
  CurrentPos := BlockStartOffset;
  for I := 0 to BlockCount - 1 do
    DrawSingleBlock(TJvDockVSBlockAccess(Block[I]));
end;

procedure THackJvDockVSChannel.ResetBlock;
var
  I: Integer;
begin
  inherited ResetBlock;
  for I := 0 to BlockCount - 1 do
    TJvDockVSBlockAccess(Block[I]).InactiveBlockWidth := InactiveTabWidth;
end;

procedure THackJvDockVSChannel.Resize;
begin
  { Here you could widen or narrow the tabs according the total space and
    depending on the number of tabs }
  inherited Resize;
end;

Sample of widened tabs

NGLN
  • 41,230
  • 8
  • 102
  • 186
  • Thanks, NGLN! I really appreciate the depth and clarity of your response! ... I gave the code a try. It did increase the block sizes, as hoped. The only remaining issue is displaying text on each tab. You have already been more than kind, but if you have thoughts about how to display each tab's text (i.e., form caption), I'd love to hear them. – Al C Jul 09 '11 at 19:25
  • I'm blown away by the effort you're putting into helping me. Thank you! ... As such, it's all the more difficult to say the new code still isn't "working" -- the tabs still have no form captions displayed, and I'm too much of a newbie to understand the code fully. I wish I had the knowledge to figure out what's going on! – Al C Jul 10 '11 at 16:15
  • @Al Be sure not using the OnFinishSetDockPanelSize event any longer. Also, be sure to set the DockPanelClass property of the DockServer prior to setting the DockServer's style property. I.e. setting the style in the IDE is too early! – NGLN Jul 10 '11 at 16:26
  • @Al Yes, see the `TMainForm.FormCreate` event handler in my code. – NGLN Jul 10 '11 at 18:56
  • That did it! ... Thanks again. I wish I could give you more than a point and a green check mark :-) – Al C Jul 10 '11 at 19:00