home *** CD-ROM | disk | FTP | other *** search
- {*******************************************************}
- { }
- { Borland Delphi Visual Component Library }
- { }
- { Copyright (c) 1997,99 Inprise Corporation }
- { }
- {*******************************************************}
-
- unit mxbutton;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Grids, Buttons, Controls,
- StdCtrls, Forms, Dialogs, Bde, DB, DBTables, Menus, ExtCtrls,
- mxConsts, mxdb, mxstore, mxcommon;
-
- type
- TMenuProp = (tmChecked, tmRadio, tmNone);
-
- TQuickMenuItem = class(TMenuItem)
- private
- Action: Integer;
- end;
-
- TQuickMenu = class(TPopUpMenu)
- private
- FOnSelected: TNotifyEvent;
- procedure EHOnItemClick(Sender: TObject);
- public
- FAction: Integer;
- iDim: Integer;
- dimGroup: TDimGroup;
- isGroupStart: Boolean;
- Index: Integer;
- Cell: Integer;
- ValueIndex: Integer;
- procedure Clear;
- procedure SetTitle(value: String);
- procedure AddLine(const value: String; Prop: TMenuProp; Action: Integer);
- procedure PopUpAtMe(aControl: TWinControl; x,y: Integer);
- property OnSelected: TNotifyEvent read FOnSelected write FonSelected;
- end;
-
- TPivotButtonMouseState = (xmNone, xmPushed, xmDragging);
- TPivotButtonType = (pbDimension, pbTarget, pbSummary, pbInactive);
-
- TPivotButton = class(TSpeedButton)
- private
- FType: TPivotButtonType;
- FSource: TDecisionSource;
- FMenu: TQuickMenu;
- FMouseState: TPivotButtonMouseState;
- SaveX: Integer;
- SaveY: Integer;
- myDim: Integer;
- myDimInfo: TDimInfo;
- procedure SetState(Value: TPivotButtonMouseState);
- procedure SetMyDim(iDim: Integer);
- procedure SetDecisionSource(Value: TDecisionSource);
- procedure SelectButtonValue;
- procedure SelectButtonProperties;
- procedure EHOnValue(Sender: TObject);
- procedure EHOnProperty(Sender: TObject);
- protected
- procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
- procedure DragCanceled; override;
- procedure Paint; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Click; override;
- procedure DragDrop(Source: TObject; X, Y: Integer); override;
- property DimInfo:TDimInfo read myDimInfo;
- procedure NewState;
- procedure SetType(Value: TPivotButtonType);
- published
- property Parent;
- property DecisionSource: TDecisionSource read FSource write SetDecisionSource;
- property iDim: Integer read myDim write SetMyDim;
- end;
-
- TDecisionButtonPosition = (xtHorizontal, xtVertical, xtLeftTop);
- TDecisionButtonGrouping = (xtCheck, xtRadio, xtSequential);
-
- TDecisionPivotOption = (xtRows, xtColumns, xtSummaries);
- TDecisionPivotOptions = set of TDecisionPivotOption;
-
- implementation
-
- const
- crDimMove = 100;
- crDimIns = 101;
- bmpRows = 102;
- bmpCols = 103;
-
- { TPivotButton methods }
-
- constructor TPivotButton.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- SetState(xmNone);
- AllowAllUp := True;
- Enabled := True;
- Caption := '';
- GroupIndex := 0;
- Screen.Cursors[crDimMove] := LoadCursor(HInstance, 'DIMMOVE');
- Screen.Cursors[crDimIns] := LoadCursor(HInstance, 'DIMINS');
- end;
-
- destructor TPivotButton.Destroy;
- begin
- FMenu.free;
- FMenu := nil;
- inherited Destroy;
- end;
-
- procedure TPivotButton.SetDecisionSource(Value: TDecisionSource);
- begin
- if (Value <> FSource) then FSource := Value;
- end;
-
- procedure TPivotButton.SetMyDim(iDim: Integer);
- begin
- myDim := iDim;
- NewState;
- end;
-
- procedure TPivotButton.SetType(Value: TPivotButtonType);
- begin
- FType := Value;
- end;
-
- procedure TPivotButton.NewState;
- begin
- if (myDim >= 0) and assigned(FSource) and (myDim <= FSource.nDims) then
- begin
- myDimInfo.iGroup := FSource.GetGroup(myDim);
- myDimInfo.iValue := FSource.GetValue(myDim);
- myDimInfo.iState := FSource.GetState(myDim);
- myDimInfo.iRowState := FSource.GetRowState(myDim);
- myDimInfo.iIndex := FSource.GetIndex(myDim, False);
- myDimInfo.iActiveIndex := FSource.GetIndex(myDim, True);
- FType := pbDimension;
- end
- else
- begin
- Caption := '';
- myDimInfo.IIndex := -1;
- myDimInfo.IActiveIndex := -1;
- end;
- flat := (myDimInfo.IState in [dmDrilled, dmPaged]) or (FType in [pbSummary, pbTarget, pbInactive]);
-
- if (MyDimInfo.IState = dmOpen) then
- Down := True
- else
- Down := False;
- SetState(xmNone);
- Invalidate;
- end;
-
- procedure TPivotButton.CMDesignHitTest(var Msg: TCMDesignHitTest);
- begin
- if (Msg.Pos.X>Width shr 2) and (msg.Pos.x<width-width shr 2) and
- (msg.Pos.Y>Height shr 2) and (msg.Pos.Y<Height-height shr 2) then
- Msg.Result := 1
- else
- msg.Result := 0;
- end;
-
- procedure TPivotButton.Click;
- begin
- case FType of
- pbSummary,
- pbInactive: SelectButtonValue;
- pbDimension:
- if (myDimInfo.IState in [dmDrilled, dmPaged]) then
- SelectButtonValue
- else if (FMouseState <> xmDragging) then
- DecisionSource.ToggleDimIndex(myDimInfo.iGroup, myDimInfo.IIndex, False);
- end;
- end;
-
- procedure TPivotButton.Mouseup(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if (FType = pbDimension) and (Button = mbRight) then
- begin
- SelectButtonProperties;
- end;
- if (Ftype <> pbTarget) and (Button = mbLeft) and (FMouseState = xmPushed) then
- Click;
- SetState(xmNone);
- end;
-
- procedure TPivotButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if (FType = pbTarget) then Exit;
- if (Button = mbLeft) then
- begin
- SetState(xmPushed);
- SaveX := X;
- SaveY := Y;
- end;
- end;
-
- procedure TPivotButton.MouseMove(Shift: TShiftState; X, Y: Integer);
- begin
- inherited;
- if (FMouseState = xmPushed) and (FType = pbDimension) then
- begin
- if (abs(X-SaveX)>5) or (abs(SaveY-Y)>5) or (X=0) or (X=Width) or (Y=0) or (Y= Height) then
- begin
- SetState(xmDragging);
- BeginDrag(True);
- end;
- end;
- end;
-
- procedure TPivotButton.DragCanceled;
- begin
- SetState(xmNone);
- end;
-
- procedure TPivotButton.SetState;
- begin
- FMouseState := value;
- end;
-
- procedure TPivotButton.SelectButtonProperties;
- begin
- if (FType = pbDimension) then
- begin
- if not (myDimInfo.iGroup in [dgRow, dgCol]) then
- Exit;
- if not assigned (FMenu) then
- FMenu := TQuickMenu.Create(self);
- FMenu.Clear;
- if (mydiminfo.iGroup = dgRow) then
- FMenu.AddLine(sMoveToCol, tmNone, 0)
- else if (myDimInfo.iGroup = dgCol) then
- FMenu.AddLine(sMoveToRow, tmNone, 0);
- if (myDimInfo.iState <> dmPaged) then
- begin
- if (myDimInfo.IState <> dmDrilled) then
- FMenu.AddLine(sDrilled, tmNone, 1)
- else
- FMenu.AddLine(sDrilled, tmChecked, 1);
- end;
- FMenu.OnSelected := EHOnProperty;
- FMenu.PopUpAtMe(TWinControl(self),0,Height);
- end;
- end;
-
- procedure TPivotButton.SelectButtonValue;
- var
- action,i,j,limit: Integer;
- aVariant: variant;
- DM: TCubeDim;
- begin
- if not assigned(DecisionSource) then Exit;
- if (FType = pbSummary) then
- begin
- if not assigned (FMenu) then
- FMenu := TQuickMenu.Create(self);
- FMenu.Clear;
- for i := 0 to DecisionSource.nSums-1 do
- begin
- FMenu.AddLine(DecisionSource.GetSummaryName(i), tmNone, i);
- end;
- FMenu.OnSelected := EHOnValue;
- FMenu.PopUpAtMe(TWinControl(self),0,Height);
- end
- else if (Ftype = pbInactive) then
- begin
- if not assigned (FMenu) then
- FMenu := TQuickMenu.Create(self);
- FMenu.Clear;
- for i := 0 to DecisionSource.DecisionCube.DimensionMap.count-1 do
- begin
- DM := DecisionSource.DecisionCube.DimensionMap[i];
- if (not DM.Loaded) and (DM.ActiveFlag <> diInActive) then
- begin
- FMenu.AddLine(DM.FieldName, tmNone, i);
- end;
- end;
- FMenu.OnSelected := EHOnValue;
- FMenu.PopUpAtMe(TWinControl(self),0,Height);
- end
- else if (FType = pbDimension) then
- begin
- if not assigned (FMenu) then
- FMenu := TQuickMenu.Create(self);
- FMenu.Clear;
- limit := DecisionSource.GetDimensionMemberCount(myDim);
- if (myDimInfo.IState = dmPaged) then
- begin
- action := 2;
- for i := 0 to DecisionSource.GetDimensionMemberCount(myDim)-1 do
- begin
- DM := DecisionSource.DecisionCube.DimensionMap[myDim];
- aVariant := DecisionSource.GetMemberAsVariant(myDim, i);
- aVariant := DM.GetBinValues(aVariant);
- if (VarType(aVariant) < varArray) then
- FMenu.AddLine(FormatVariant(aVariant, ''), tmNone, Action)
- else
- begin
- for j := VarArrayLowBound(aVariant,1) to VarArrayHighBound(aVariant,1) do
- begin
- FMenu.AddLine(FormatVariant(aVariant[j], ''), tmNone, Action);
- action := action + 1;
- end;
- end;
- end;
- end
- else
- begin
- FMenu.AddLine(sMakeDimOpen, tmNone, 0);
- FMenu.AddLine(SAllValues, tmNone, 1);
- FMenu.AddLine('-', tmNone, -1);
- for i := 0 to limit-1 do
- begin
- FMenu.AddLine(DecisionSource.GetMemberAsString(myDim,i), tmNone, i+2);
- end;
- end;
- FMenu.OnSelected := EHOnValue;
- FMenu.PopUpAtMe(TWinControl(self),0,Height);
- end;
- end;
-
- procedure TPivotButton.EHOnValue(Sender: TObject);
- var
- DM: TCubeDim;
- myMap: TCubeDims;
- i,j, si,ci: integer;
- aVariant, bVariant: variant;
- action: integer;
- begin
- Action := FMenu.FAction;
- FMenu.free;
- FMenu := nil;
- if (FType = pbSummary) then
- DecisionSource.SetCurrentSummary(Action)
- else if (FType = pbInactive) then
- begin
- myMap := TCubeDims.Create(DecisionSource.DecisionCube, TCubeDim);
- try
- myMap.Assign(DecisionSource.DecisionCube.DimensionMap);
- for i := 0 to myMap.count-1 do
- begin
- myMap[i].loaded := False;
- end;
- if (myMap[action].isSummary) and (myMap[action].derivedFrom > 0) then
- begin
- if myMap.averageFieldCheck(action, si, ci) then
- begin
- myMap[si].loaded := True;
- myMap[ci].loaded := True;
- end;
- end
- else myMap[action].loaded := True;
- try
- DecisionSource.DecisionCube.Refresh(myMap, True);
- except
- on E: EDimensionMapError do
- begin
- raise exception.create(sCouldNotOpen + E.message);
- end;
- end;
- finally
- myMap.free;
- end;
- end
- else if (FType = pbDimension) then
- begin
- if (Action = 0) then
- begin
- DecisionSource.ToggleDimIndex(myDimInfo.iGroup, myDimInfo.IIndex, False);
- end
- else if (Action = 1) then
- begin
- DecisionSource.DrillDimIndex(myDimInfo.iGroup, myDimInfo.iIndex, -1, False);
- end
- else if (myDimInfo.iState = dmPaged) then
- begin
- Action := Action - 2;
- myMap := TCubeDims.Create(DecisionSource.DecisionCube, TCubeDim);
- try
- myMap.Assign(DecisionSource.DecisionCube.DimensionMap);
- DM := myMap[myDim];
- for i := 0 to DecisionSource.GetDimensionMemberCount(myDim)-1 do
- begin
- aVariant := DecisionSource.GetMemberAsVariant(myDim, i);
- aVariant := DM.GetBinValues(aVariant);
- if (VarType(aVariant) < varArray) then
- Action := Action - 1
- else
- begin
- for j := VarArrayLowBound(aVariant,1) to VarArrayHighBound(aVariant,1) do
- begin
- action := action - 1;
- if (Action < 0) then
- begin
- bVariant := aVariant[j];
- aVariant := bVariant;
- break;
- end;
- end;
- end;
- if (Action < 0) then
- break;
- end;
- DM.StartValue := FormatVariant(aVariant,'');
- try
- DecisionSource.DecisionCube.Refresh(myMap, True );
- except
- on E: EDimensionMapError do
- begin
- raise exception.create(sCouldNotOpen + E.message);
- end;
- end;
- finally
- myMap.free;
- end;
- Exit;
- end
- else
- DecisionSource.DrillDimIndex(myDimInfo.iGroup, myDimInfo.iIndex, Action-2, False);
- end;
- end;
-
- procedure TPivotButton.EHOnProperty(Sender: TObject);
- var
- toGroup: TDimGroup;
- begin
- try
- if (FType = pbDimension) then
- begin
- if assigned(FMenu) then
- begin
- if (FMenu.FAction = 0) then
- begin
- if (myDimInfo.iGroup = dgRow) then
- toGroup := dgCol
- else
- toGroup := dgRow;
- FSource.MoveDimIndexes(myDimInfo.iGroup, toGroup, myDimInfo.IIndex, 0, False);
- end
- else if (FMenu.FAction = 1) then
- begin
- if (myDimInfo.Istate = dmDrilled) then
- DecisionSource.ToggleDimIndex(mydiminfo.iGroup, myDimInfo.IIndex, False)
- else
- DecisionSource.DrillDimIndex(mydiminfo.iGroup, myDimInfo.iIndex, -1, False);
- end;
- end;
- end;
- finally
- FMenu.Free;
- FMenu := nil;
- end;
- end;
-
- procedure TPivotButton.Paint;
- var
- mid, split, x,y: Integer;
- FBmp: TBitMap;
- aRect: TRect;
- fString, string2: ShortString;
- sHeight,sMargin: Integer;
- i,ArrowX: Integer;
- ArrowString: ShortString;
- aChar: char;
- Map: TCubeDims;
- begin
- inherited;
- if not assigned(FSource) then Exit;
- ARect.Left := 0;
- ARect.Right := Width;
- ARect.Top := 0;
- ARect.Bottom := Height;
- if (FType = pbDimension) or (FType = pbInactive) or (FType = pbSummary) or (FType = pbTarget) then
- with Canvas do
- begin
- if (Ftype = pbTarget) then
- begin
- FBmp := TBitmap.Create;
- try
- if (mydiminfo.iGroup = dgRow) then
- FBmp.LoadFromResourceName(HInstance, 'Rows')
- else
- FBmp.LoadFromResourceName(HInstance, 'Cols');
- x := (ARect.Right-FBMP.Width) div 2;
- y := (ARect.Bottom - FBMP.Height) div 2;
- BrushCopy(Rect(x, y, x+FBmp.width, y+FBmp.height), FBMP, Rect(0,0,FBmp.Width,FBmp.Height), clMaroon);
- finally
- FBmp.Free;
- end;
- Exit;
- end;
- sHeight := TextHeight('XXX');
- if (FType = pbInactive) then
- begin
- string2 := '';
- arrowString := '6';
- fString := sActivateLabel;;
- end
- else if (Ftype = pbSummary) then
- begin
- string2 := '';
- arrowString := '6';
- i := FSource.CurrentSum;
- fString := FSource.GetSummaryName(i);
- end
- else if (FType = pbDimension) then
- begin
- if (myDimInfo.IState = dmPaged) then
- begin
- Map := FSource.DecisionCube.DimensionMap;
- String2 := FSource.GetDimensionName(myDim) + '=';
- if Assigned(Map[myDim].BinData) then
- fString := FormatVariant(Map[myDim].BinData.GetIBinValue(0,0), '')
- else
- fString := '';
- arrowString := '';
- end
- else if (myDimInfo.IState = dmDrilled) then
- begin
- String2 := FSource.GetDimensionName(myDim) + '=';
- if (myDimInfo.IValue >= 0) then
- fString := FSource.GetMemberAsString(myDim, myDimInfo.IValue)
- else
- fString := SAllValues;
- arrowString := '6';
- end
- else
- begin
- string2 := '';
- arrowString := '';
- if (myDim >= 0) then
- fString := FSource.GetDimensionName(myDim);
- end;
- end;
- if (TextWidth(FString+ArrowString) > (Width-4))
- and (string2 = '') and (Height > ((sHeight*3) div 2)) then
- begin
- mid := length(fString) div 2;
- split := 0;
- for i := length(fString) downto 2 do
- begin
- aChar := fString[i];
- if (aChar < 'A') or ((aChar>'Z') and (aChar<'a')) or (aChar>'z') then
- begin
- if abs(mid-i) < abs(mid-split) then
- split := i;
- end;
- end;
- if (split = 0) then
- for i := length(fString) downto 2 do
- begin
- if (fString[i] <= 'Z') and (fString[i-1] > 'Z') then
- begin
- if abs(mid-i) < abs(mid-split) then
- split := i;
- end;
- end;
- if (split > 0) then
- begin
- string2 := Copy(fString,1, split-1);
- if (fString[split] = ' ') then
- split := split + 1;
- fString := Copy(fString,split, length(fString));
- end;
- end;
- while (TextWidth(fString+ArrowString) > (Width-4)) and (Length(fString) > 0) do
- Delete(fString, Length(fString), 1);
- while (TextWidth(string2) > (Width-4)) do
- Delete(String2, Length(String2), 1);
- x := ARect.Right-ARect.Left-TextWidth(FString+ArrowString);
- if (x <= 0) then
- x := ARect.Left
- else
- x := ARect.Left + (x div 2);
- ArrowX := x + TextWidth(fString);
- sMargin := (Height-2*(sHeight)) div 2;
- if (sMargin >= 0) and (string2 <> '') then
- begin
- y := ARect.Bottom - sHeight - (sMargin);
- TextOut(x, y, fString);
- x := Width-TextWidth(String2);
- if (x <= 0) then
- x := ARect.Left
- else
- x := ARect.Left + (x div 2);
- TextOut(x, ARect.Top+(sMargin), String2);
- end
- else
- begin
- y := (ARect.Top + ARect.Bottom - TextHeight(fString)) div 2;
- if (y < 0) then y := 0;
- TextOut(x, y, fString);
- end;
- if (ArrowString <> '') then
- begin
- Font.Name := 'Marlett';
- Font.Charset := Default_CharSet;
- Font.Pitch := fpDefault;
- Font.Style := [];
- TextOut(ArrowX, y, ArrowString);
- end;
- end;
- end;
- procedure TPivotButton.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
- var
- sdimGroup, ddimGroup: TDimGroup;
- sIndex, dIndex: Integer;
- begin
- inherited;
- Accept := False;
- if (FType = pbSummary) then Exit;
- if not (Source is TPivotButton) then Exit;
- if TPivotButton(Source).FSource <> FSource then Exit;
- ddimGroup := mydiminfo.iGroup;
- sdimGroup := TPivotButton(Source).MyDimInfo.IGroup;
- sIndex := TPivotButton(Source).MyDimInfo.IIndex;
- dIndex := MyDimInfo.IIndex;
- if (FType = pbTarget) or (X > (Width - (Width div 8))) then { add to the right }
- begin
- if (ddimGroup = sdimGroup) and ((dIndex = (sIndex-1)) or (dIndex = sIndex)) then
- Exit;
- TPivotButton(Source).DragCursor := crDimIns;
- end
- else if (X < Width div 8) then
- begin
- if (ddimGroup = sdimGroup) and (dIndex = (sIndex + 1)) then Exit;
- TPivotButton(Source).DragCursor := crDimIns;
- end
- else
- begin
- if (ddimGroup = sdimGroup) and (dIndex = sIndex) then
- TPivotButton(Source).DragCursor := crDimMove;
- TPivotButton(Source).DragCursor := crDimMove;
- end;
- Accept := True;
- end;
-
- procedure TPivotButton.DragDrop(Source: TObject; X, Y: Integer);
- var
- sdimGroup, ddimGroup: TDimGroup;
- sIndex, dIndex: Integer;
- begin
- inherited;
- ddimGroup := mydiminfo.iGroup;
- sdimGroup := TPivotButton(Source).MyDimInfo.IGroup;
- sIndex := TPivotButton(Source).MyDimInfo.IIndex;
- dIndex := MyDimInfo.IIndex;
- if (ddimGroup = sdimGroup) and (sIndex = dIndex) then
- Exit; { do not drop on self }
- if (FType = pbTarget) or (X > (Width - (Width div 8))) then
- FSource.MoveDimIndexes(sdimGroup, ddimGroup, sIndex, dIndex+1, False)
- else if (X < (Width div 8)) then
- FSource.MoveDimIndexes(sdimGroup, ddimGroup, sIndex, dIndex, False)
- else
- FSource.SwapDimIndexes(sdimGroup, ddimGroup, sIndex, dIndex, False);
- end;
-
- procedure TQuickMenu.Clear;
- begin
- while (Items.count > 0) do
- Items.Delete(0);
- end;
-
- procedure TQuickMenu.PopUpAtMe(aControl: TWinControl; x,y: Integer);
- var
- aPoint: TPoint;
- begin
- aPoint.x := x;
- aPoint.y := y;
- aPoint := aControl.ClientToScreen(aPoint);
- PopUp(aPoint.x, aPoint.y);
- end;
-
- procedure TQuickMenu.AddLine(const value: string; Prop: TMenuProp; Action: Integer);
- var
- aMenuItem: TQuickMenuitem;
- begin
- aMenuItem := TQuickMenuItem.Create(self);
- aMenuItem.Action := Action;
- aMenuItem.Caption := value;
- aMenuItem.Enabled := True;
- aMenuItem.OnClick := EHOnItemClick;
- if (Prop = tmChecked) then aMenuItem.Checked := True;
- if (Prop = tmRadio) then
- begin
- aMenuItem.Checked := True;
- aMenuItem.RadioItem := True;
- end;
- Items.Add(aMenuItem);
- end;
-
- procedure TQuickMenu.SetTitle(value: string);
- begin
- Clear;
- AddLine(value, tmNone, -1);
- AddLine('-', tmNone, -1);
- end;
-
- procedure TQuickMenu.EHOnItemClick(Sender: TObject);
- var
- i: Integer;
- begin
- for i := 0 to Items.count-1 do
- begin
- if (Sender = Items[i]) then
- begin
- FAction := TQuickMenuItem(Items[i]).Action;
- if (FAction >= 0) and assigned (FOnSelected) then
- FOnSelected(self);
- Exit;
- end;
- end;
- end;
-
- end.
-