unit uViewDetallesBase; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uViewBase, cxStyles, ComCtrls, ToolWin, ActnList, cxCustomData, cxGraphics, cxFilter, cxData, cxDataStorage, cxEdit, DB, cxDBData, uDADataTable, cxGridLevel, cxClasses, cxControls, cxGridCustomView, cxGridCustomTableView, cxGridTableView, cxGridDBTableView, ImgList, PngImageList, cxGrid, cxImageComboBox, cxTextEdit, cxMaskEdit, cxCheckBox, uGridStatusUtils, uControllerDetallesBase, cxCurrencyEdit, ExtCtrls, Grids, DBGrids, StdCtrls, ExtActns, StdActns, cxRichEdit, JvExStdCtrls, JvCombobox, JvColorCombo, TB2Item, TBX, TB2Dock, TB2Toolbar, uDAInterfaces, cxContainer, Menus, cxGridCustomPopupMenu, cxGridPopupMenu; type IViewDetallesBase = interface(IViewBase) ['{852EB860-13B6-4355-A6B0-4542AB16896F}'] procedure ExpandirTodo; procedure ContraerTodo; procedure AjustarAncho; procedure GotoFirst; procedure GotoLast; procedure SaveGridStatus; procedure RestoreGridStatus; procedure SeleccionarTodo; procedure BeginUpdate; procedure EndUpdate; function IsEmpty : Boolean; function GetFocusedView : TcxGridDBTableView; property _FocusedView : TcxGridDBTableView read GetFocusedView; function GetGrid : TcxGrid; property _Grid : TcxGrid read GetGrid; end; TfrViewDetallesBase = class(TfrViewBase, IViewDetallesBase) ActionListContenido: TActionList; DADataSource: TDADataSource; actAnadir: TAction; actEliminar: TAction; actSubir: TAction; actBajar: TAction; ContenidoImageList: TPngImageList; ToolBar1: TToolBar; cxStyleRepository: TcxStyleRepository; ToolButton1: TToolButton; ToolButton2: TToolButton; ToolButton3: TToolButton; ToolButton4: TToolButton; cxGrid: TcxGrid; cxGridView: TcxGridDBTableView; cxGridViewID: TcxGridDBColumn; cxGridViewPOSICION: TcxGridDBColumn; cxGridViewTIPO: TcxGridDBColumn; cxGridViewDESCRIPCION: TcxGridDBColumn; cxGridViewCANTIDAD: TcxGridDBColumn; cxGridViewIMPORTEUNIDAD: TcxGridDBColumn; cxGridViewIMPORTETOTAL: TcxGridDBColumn; cxGridViewVISIBLE: TcxGridDBColumn; cxGridLevel: TcxGridLevel; RichEditBold1: TRichEditBold; RichEditItalic1: TRichEditItalic; ToolButton6: TToolButton; ToolButton7: TToolButton; RichEditUnderline1: TRichEditUnderline; RichEditAlignLeft1: TRichEditAlignLeft; RichEditAlignRight1: TRichEditAlignRight; RichEditAlignCenter1: TRichEditAlignCenter; ToolButton8: TToolButton; ToolButton9: TToolButton; ToolButton10: TToolButton; ToolButton11: TToolButton; ToolButton12: TToolButton; ToolButton13: TToolButton; FontEdit1: TFontEdit; ToolButton14: TToolButton; UpDown1: TUpDown; FontSize: TEdit; FontName: TJvFontComboBox; TBXDock1: TTBXDock; TBXToolbar1: TTBXToolbar; TBXItem1: TTBXItem; TBXItem2: TTBXItem; TBXSeparatorItem1: TTBXSeparatorItem; TBXItem3: TTBXItem; TBXItem4: TTBXItem; TBXSeparatorItem2: TTBXSeparatorItem; TBXItem5: TTBXItem; TBXItem6: TTBXItem; TBXItem7: TTBXItem; TBXSeparatorItem3: TTBXSeparatorItem; TBXItem8: TTBXItem; TBXSeparatorItem4: TTBXSeparatorItem; TBXItem9: TTBXItem; TBXItem10: TTBXItem; TBXItem11: TTBXItem; cxStyle_SUBTOTAL: TcxStyle; cxStyle_TITULO: TcxStyle; actAnchoAutomatico: TAction; TBXSeparatorItem5: TTBXSeparatorItem; TBXItem13: TTBXItem; cxStyle_DESCUENTO: TcxStyle; actDetallesCortar: TAction; actDetallesCopiar: TAction; actDetallesPegar: TAction; cxStyle_SOLO_LECTURA: TcxStyle; cxStyle_ESPECIALES: TcxStyle; cxStyle_NORMAL_PAR: TcxStyle; cxStyle_NORMAL_IMPAR: TcxStyle; TBXSubmenuItem1: TTBXSubmenuItem; TBXSeparatorItem6: TTBXSeparatorItem; actAnadirCapitulo: TAction; actAnadirTitulo: TAction; actAnadirSubtotal: TAction; actAnadirDescuento: TAction; TBXItem12: TTBXItem; TBXItem14: TTBXItem; TBXItem15: TTBXItem; TBXItem16: TTBXItem; TBXSeparatorItem7: TTBXSeparatorItem; cxGridPopupMenu: TcxGridPopupMenu; GridGeneralPopupMenu: TPopupMenu; dsds1: TMenuItem; Bajar1: TMenuItem; Eliminar1: TMenuItem; N1: TMenuItem; Copiar1: TMenuItem; Copiar2: TMenuItem; Pegar1: TMenuItem; N3: TMenuItem; Aadir2: TMenuItem; N4: TMenuItem; Anchoautomtico2: TMenuItem; actExportar: TAction; ExportaraMicrosoftExcel1: TMenuItem; actSeleccionarTodo: TAction; Seleccionartodo1: TMenuItem; cxStyle_TITULO_OPCIONAL: TcxStyle; TBXItem17: TTBXItem; TBXItem19: TTBXItem; TBXItem20: TTBXItem; actAnadirCapituloOpcional: TAction; actAnadirTituloOpcional: TAction; procedure actAnadirExecute(Sender: TObject); procedure actEliminarExecute(Sender: TObject); procedure actSubirExecute(Sender: TObject); procedure actBajarExecute(Sender: TObject); procedure actEliminarUpdate(Sender: TObject); procedure actSubirUpdate(Sender: TObject); procedure actBajarUpdate(Sender: TObject); procedure actAnadirUpdate(Sender: TObject); procedure cxGridViewEditValueChanged(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem); procedure cxGridViewEditKeyDown(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; var Key: Word; Shift: TShiftState); procedure cxGridViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure cxGridViewInitEdit(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit); procedure FontEdit1BeforeExecute(Sender: TObject); procedure FontEdit1Accept(Sender: TObject); procedure CustomViewCreate(Sender: TObject); procedure CustomViewDestroy(Sender: TObject); procedure FontSizeChange(Sender: TObject); procedure FontNameChange(Sender: TObject); procedure cxGridViewEditing(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; var AAllow: Boolean); procedure cxGridViewStylesGetContentStyle(Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; AItem: TcxCustomGridTableItem; out AStyle: TcxStyle); procedure TBXItem13Click(Sender: TObject); procedure actAnchoAutomaticoExecute(Sender: TObject); procedure actAnchoAutomaticoUpdate(Sender: TObject); procedure actAnadirCapituloUpdate(Sender: TObject); procedure actAnadirCapituloOpcionalUpdate(Sender: TObject); procedure actAnadirTituloUpdate(Sender: TObject); procedure actAnadirTituloOpcionalUpdate(Sender: TObject); procedure actAnadirSubtotalUpdate(Sender: TObject); procedure actAnadirDescuentoUpdate(Sender: TObject); procedure actAnadirCapituloExecute(Sender: TObject); procedure actAnadirCapituloOpcionalExecute(Sender: TObject); procedure actAnadirTituloExecute(Sender: TObject); procedure actAnadirTituloOpcionalExecute(Sender: TObject); procedure actAnadirSubtotalExecute(Sender: TObject); procedure actAnadirDescuentoExecute(Sender: TObject); procedure actDetallesCopiarExecute(Sender: TObject); procedure actDetallesCopiarUpdate(Sender: TObject); procedure actDetallesPegarExecute(Sender: TObject); procedure actSeleccionarTodoExecute(Sender: TObject); procedure actSeleccionarTodoUpdate(Sender: TObject); procedure actDetallesPegarUpdate(Sender: TObject); procedure actDetallesCortarExecute(Sender: TObject); procedure actDetallesCortarUpdate(Sender: TObject); procedure cxGridViewFocusedItemChanged(Sender: TcxCustomGridTableView; APrevFocusedItem, AFocusedItem: TcxCustomGridTableItem); procedure cxGridViewFocusedRecordChanged(Sender: TcxCustomGridTableView; APrevFocusedRecord, AFocusedRecord: TcxCustomGridRecord; ANewItemRecordFocusingChanged: Boolean); procedure actExportarExecute(Sender: TObject); procedure cxGridViewDESCRIPCIONGetDisplayText( Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord; var AText: string); private FController : IControllerDetallesBase; FDetalles: IDAStronglyTypedDataTable; FGridStatus: TcxGridStatus; CurEdit: TcxRichEdit; FUpdating: Boolean; function CurrText: TTextAttributes; // procedure OnSelectChange(Sender:TObject); function GetController: IControllerDetallesBase; procedure SetController(const Value: IControllerDetallesBase); function GetDetalles: IDAStronglyTypedDataTable; procedure SetDetalles(const Value: IDAStronglyTypedDataTable); function DarPosicionCAMPO(const Nombre:String): Integer; procedure DoPasteText(Sender: TObject; AText: string); procedure TratamientoTeclas(Key: Word; Shift: TShiftState; AItem: TcxCustomGridTableItem = nil); protected function DarListaSeleccionados: TIntegerArray; function HayQueRecalcular(AItem: TcxCustomGridTableItem): Boolean; virtual; function EsTipoEditable(AItem: TcxCustomGridTableItem): Boolean; virtual; function DarTipoConcepto(ARecord: TcxCustomGridRecord): string; virtual; function DarFuentePorDefecto(const ATipo : String = TIPO_DETALLE_CONCEPTO): TFont; virtual; function GetFocusedView : TcxGridDBTableView; virtual; function GetGrid : TcxGrid; virtual; procedure SeleccionarFilaActual; public procedure GotoFirst; procedure GotoLast; procedure BeginUpdate; procedure EndUpdate; procedure SaveGridStatus; procedure RestoreGridStatus; procedure ExpandirTodo; procedure ContraerTodo; procedure AjustarAncho; procedure SeleccionarTodo; function IsEmpty : Boolean; destructor Destroy; override; property _FocusedView : TcxGridDBTableView read GetFocusedView; property _Grid : TcxGrid read GetGrid; property Controller: IControllerDetallesBase read GetController write SetController; property Detalles: IDAStronglyTypedDataTable read GetDetalles write SetDetalles; end; implementation {$R *.dfm} uses uDMBase, uCalculosUtils, dxOffice11, uSistemaFunc, uGridClipboardUtils, Clipbrd, cxGridExportLink, uRTFUtils; type TOnPaste = procedure(Sender: TObject; AText: string) of object; TcxMyRichEdit = class(TcxRichEdit) private FOnPaste: TOnPaste; FOldWndProc : TWndMethod; FGrid: TcxGrid; procedure InnerControlWindowProc(var Message: TMessage); procedure FInnerRichOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); protected procedure DoPaste; virtual; procedure Initialize; override; procedure HookInnerControl; public procedure PasteFromClipboard; override; destructor Destroy; override; property _Grid : TcxGrid read FGrid write FGrid; property OnPaste: TOnPaste read FOnPaste write FOnPaste; end; TcxMyRichEditProperties = class(TcxRichEditProperties) public class function GetContainerClass: TcxContainerClass; override; end; var _FRecalculando : Boolean; _FRecalcular : Boolean; _FPegando : Boolean; function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric; FontType: Integer; Data: Pointer): Integer; stdcall; begin TStrings(Data).Add(LogFont.lfFaceName); Result := 1; end; procedure TfrViewDetallesBase.actAnadirCapituloExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := _FocusedView.OptionsSelection.MultiSelect; if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then begin Controller.Add(FDetalles, TIPO_DETALLE_TITULO); Controller.Add(FDetalles, TIPO_DETALLE_CONCEPTO); Controller.Add(FDetalles, TIPO_DETALLE_CONCEPTO); Controller.Add(FDetalles, TIPO_DETALLE_SUBTOTAL); // Controller.add(FDetalles, TIPO_DETALLE_DESCUENTO); end; finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirCapituloOpcionalExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := _FocusedView.OptionsSelection.MultiSelect; if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then begin Controller.Add(FDetalles, TIPO_DETALLE_TITULO_OPCIONAL); Controller.Add(FDetalles, TIPO_DETALLE_CONCEPTO); Controller.Add(FDetalles, TIPO_DETALLE_CONCEPTO); Controller.Add(FDetalles, TIPO_DETALLE_SUBTOTAL); // Controller.add(FDetalles, TIPO_DETALLE_DESCUENTO); end; finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirCapituloOpcionalUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnadirCapituloUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnadirDescuentoExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Add(FDetalles, TIPO_DETALLE_DESCUENTO); finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirDescuentoUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnadirExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Add(FDetalles, TIPO_DETALLE_CONCEPTO); finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirSubtotalExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Add(FDetalles, TIPO_DETALLE_SUBTOTAL); finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirSubtotalUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnadirTituloExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then cxGridView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Add(FDetalles, TIPO_DETALLE_TITULO); finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirTituloOpcionalExecute(Sender: TObject); var bEsMultiSelect : Boolean; begin // Debo quitar el multiselect porque provoca que se quede seleccionado // el registro actual y no el nuevo registro que voy a añadir bEsMultiSelect := cxGridView.OptionsSelection.MultiSelect; if bEsMultiSelect then cxGridView.OptionsSelection.MultiSelect := False; ShowHourglassCursor; _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Add(FDetalles, TIPO_DETALLE_TITULO_OPCIONAL); finally _FocusedView.EndUpdate; HideHourglassCursor; // Dejo la propiedad MultiSelect como estaba if bEsMultiSelect then _FocusedView.OptionsSelection.MultiSelect := bEsMultiSelect; end; end; procedure TfrViewDetallesBase.actAnadirTituloOpcionalUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnadirTituloUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actEliminarExecute(Sender: TObject); var AuxTop, AuxRow:Integer; begin ShowHourglassCursor; _FocusedView.BeginUpdate; try if Assigned(Controller) and Assigned(FDetalles) then begin AuxTop := cxGridView.Controller.TopRowIndex; AuxRow := cxGridView.DataController.FocusedRowIndex; Controller.Delete(FDetalles, darListaSeleccionados); if (FDetalles.RecordCount > 0) then begin //Selecciona en el grid el registro siguiente if (AuxRow < cxGridView.DataController.RowCount-1) then Inc(AuxRow) else Dec(AuxRow); _FocusedView.DataController.SelectRows(AuxRow,AuxRow); _FocusedView.Controller.TopRowIndex := AuxTop; end; end finally _FocusedView.EndUpdate; HideHourglassCursor; end; SeleccionarFilaActual; end; procedure TfrViewDetallesBase.actEliminarUpdate(Sender: TObject); begin if not Assigned(DADataSource.DataTable) then (Sender as TAction).Enabled := False else (Sender as TAction).Enabled := (not ReadOnly) and (not DADataSource.DataTable.IsEmpty) end; procedure TfrViewDetallesBase.actExportarExecute(Sender: TObject); var AFileName : String; begin inherited; if PreguntarFicheroExcelExportar(AFileName) then ExportGridToExcel(AFileName, cxGrid, True, True, False); end; procedure TfrViewDetallesBase.actSubirUpdate(Sender: TObject); begin inherited; if not Assigned(_FocusedView.Controller.FocusedRow) then (Sender as TAction).Enabled := False else (Sender as TAction).Enabled := (not ReadOnly) and (not _FocusedView.Controller.FocusedRow.IsFirst) end; procedure TfrViewDetallesBase.AjustarAncho; begin if Assigned(_FocusedView) then _FocusedView.ApplyBestFit; end; procedure TfrViewDetallesBase.BeginUpdate; begin if Assigned(_FocusedView) then _FocusedView.BeginUpdate; end; function TfrViewDetallesBase.DarTipoConcepto(ARecord: TcxCustomGridRecord): string; var IndiceCol : Integer; begin IndiceCol := cxGridView.GetColumnByFieldName(CAMPO_TIPO).Index; Result := ARecord.DisplayTexts[IndiceCol]; end; destructor TfrViewDetallesBase.Destroy; begin FController := NIL; FDetalles := NIL; if Assigned(FGridStatus) then FreeAndNil(FGridStatus); inherited; end; procedure TfrViewDetallesBase.DoPasteText(Sender: TObject; AText: string); begin // ShowMessage(AText); end; procedure TfrViewDetallesBase.ContraerTodo; begin if Assigned(_FocusedView) then _FocusedView.ViewData.Collapse(True); end; function TfrViewDetallesBase.CurrText: TTextAttributes; begin Result := NIL; if Assigned(CurEdit) then // if CurEdit.FindSelection then if CurEdit.SelLength > 0 then Result := CurEdit.SelAttributes else Result := CurEdit.DefAttributes; end; procedure TfrViewDetallesBase.CustomViewCreate(Sender: TObject); begin inherited; //Debemos tener la certeza de que las operaciones del grid estan deshabilitadas y que //cuando pulsamos teclas de insercion flecha abajo y demas salta nuestra propia lógia del controlador cxGridView.OptionsData.Appending := False; cxGridView.OptionsData.Deleting := False; cxGridView.OptionsData.Inserting := False; CurEdit := Nil; FUpdating := False; // cxGridView.OptionsView.RowSeparatorColor := dmBase.StyleManager.Colors.ButtonSeparatorColor; cxGridViewDESCRIPCION.PropertiesClass := TcxMyRichEditProperties; end; procedure TfrViewDetallesBase.CustomViewDestroy(Sender: TObject); begin inherited; CurEdit := Nil; end; procedure TfrViewDetallesBase.cxGridViewDESCRIPCIONGetDisplayText( Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord; var AText: string); begin inherited; AText := RtfToText(AText); end; procedure TfrViewDetallesBase.cxGridViewEditing(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; var AAllow: Boolean); begin AAllow := EsTipoEditable(AItem); end; procedure TfrViewDetallesBase.cxGridViewEditKeyDown( Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; var Key: Word; Shift: TShiftState); begin inherited; TratamientoTeclas(Key, Shift, AItem); end; procedure TfrViewDetallesBase.cxGridViewEditValueChanged(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem); begin inherited; if not _FRecalcular and HayQueRecalcular(AItem) then _FRecalcular := True; end; procedure TfrViewDetallesBase.cxGridViewFocusedItemChanged( Sender: TcxCustomGridTableView; APrevFocusedItem, AFocusedItem: TcxCustomGridTableItem); begin inherited; if _FRecalcular and not _FRecalculando then //and HayQueRecalcular(APrevFocusedItem) then begin _FRecalculando := True; try if Sender.Controller.EditingController.IsEditing then Sender.Controller.EditingController.Edit.PostEditValue; Controller.ActualizarTotales(Detalles); _FRecalcular := False; finally _FRecalculando := False; end; end; end; procedure TfrViewDetallesBase.cxGridViewFocusedRecordChanged( Sender: TcxCustomGridTableView; APrevFocusedRecord, AFocusedRecord: TcxCustomGridRecord; ANewItemRecordFocusingChanged: Boolean); begin inherited; if _FRecalcular and not _FRecalculando then //and HayQueRecalcular(cxGridView.Controller.FocusedItem) then begin _FRecalculando := True; try if Sender.Controller.EditingController.IsEditing then Sender.Controller.EditingController.Edit.PostEditValue; Controller.ActualizarTotales(Detalles); _FRecalcular := False; finally _FRecalculando := False; end; end; end; procedure TfrViewDetallesBase.cxGridViewInitEdit(Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit); var FuentePorDefecto: TFont; ARecord: TcxCustomGridRecord; begin inherited; if AEdit is TcxMyRichEdit then begin TcxMyRichEdit(AEdit).OnPaste := DoPasteText; TcxMyRichEdit(AEdit)._Grid := _Grid; end; // Este exit es para que no se genere código RTF para el tamaño de la fuente // porque luego sale demasiado grande en los informes impresos. Exit; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if AEdit is TcxRichEdit then begin ARecord := AItem.FocusedCellViewInfo.GridRecord; FuentePorDefecto := DarFuentePorDefecto(DarTipoConcepto(ARecord)); try //La primera vez que accedemos al grid entra dos veces y perderiamos el editor //dando un pete. if not Assigned(CurEdit) then begin CurEdit := TcxRichEdit(AEdit); FontEdit1.Enabled := True; RichEditBold1.Enabled := True; RichEditItalic1.Enabled := True; RichEditUnderline1.Enabled := True; RichEditAlignLeft1.Enabled := True; RichEditAlignRight1.Enabled := True; RichEditAlignCenter1.Enabled := True; if not VarIsNull(AItem.EditValue) and VarIsType(AItem.EditValue, varString) then if Length(AItem.EditValue) = 0 then CurEdit.DefAttributes.Assign(FuentePorDefecto); end else begin if not VarIsNull(AItem.EditValue) and VarIsType(AItem.EditValue, varString) then if Length(AItem.EditValue) = 0 then CurEdit.DefAttributes.Assign(FuentePorDefecto); end; finally FreeAndNil(FuentePorDefecto); end; end else begin CurEdit := Nil; FontEdit1.Enabled := False; RichEditBold1.Enabled := False; RichEditItalic1.Enabled := False; RichEditUnderline1.Enabled := False; RichEditAlignLeft1.Enabled := False; RichEditAlignRight1.Enabled := False; RichEditAlignCenter1.Enabled := False; end; end; procedure TfrViewDetallesBase.cxGridViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin inherited; TratamientoTeclas(Key, Shift); end; procedure TfrViewDetallesBase.cxGridViewStylesGetContentStyle( Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; AItem: TcxCustomGridTableItem; out AStyle: TcxStyle); begin inherited; AStyle := NIL; if Assigned(AItem) then begin if Odd(ARecord.Index) then AStyle := cxStyle_NORMAL_PAR else AStyle := cxStyle_NORMAL_IMPAR; end; if Assigned(ARecord) then begin if ARecord.Values[3] = TIPO_DETALLE_TITULO then AStyle := cxStyle_TITULO; if ARecord.Values[3] = TIPO_DETALLE_TITULO_OPCIONAL then AStyle := cxStyle_TITULO_OPCIONAL; if ARecord.Values[3] = TIPO_DETALLE_SUBTOTAL then AStyle := cxStyle_SUBTOTAL; if ARecord.Values[3] = TIPO_DETALLE_DESCUENTO then AStyle := cxStyle_DESCUENTO; end; end; function TfrViewDetallesBase.DarFuentePorDefecto(const ATipo: String): TFont; begin Result := TFont.Create; if ATipo = TIPO_DETALLE_CONCEPTO then begin Result.Name := 'Tahoma'; Result.Size := 11; Result.Style := []; end; if ATipo = TIPO_DETALLE_TITULO then begin Result.Name := cxStyle_TITULO.Font.Name; Result.Color := cxStyle_TITULO.TextColor; Result.Size := cxStyle_TITULO.Font.Size; Result.Style := cxStyle_TITULO.Font.Style; end; if ATipo = TIPO_DETALLE_TITULO_OPCIONAL then begin Result.Name := cxStyle_TITULO_OPCIONAL.Font.Name; Result.Color := cxStyle_TITULO_OPCIONAL.TextColor; Result.Size := cxStyle_TITULO_OPCIONAL.Font.Size; Result.Style := cxStyle_TITULO_OPCIONAL.Font.Style; end; if ATipo = TIPO_DETALLE_SUBTOTAL then begin Result.Name := cxStyle_SUBTOTAL.Font.Name; Result.Color := cxStyle_SUBTOTAL.TextColor; Result.Size := cxStyle_SUBTOTAL.Font.Size; Result.Style := cxStyle_SUBTOTAL.Font.Style; end; if ATipo = TIPO_DETALLE_DESCUENTO then begin Result.Name := cxStyle_DESCUENTO.Font.Name; Result.Color := cxStyle_DESCUENTO.TextColor; Result.Size := cxStyle_DESCUENTO.Font.Size; Result.Style := cxStyle_DESCUENTO.Font.Style; end; end; function TfrViewDetallesBase.DarListaSeleccionados: TIntegerArray; var i, j: Integer; begin j := DarPosicionCampo(CAMPO_POSICION); with cxGridView.Controller do for i:=0 to SelectedRecordCount-1 do begin SetLength(Result, i+1); Result[i] := SelectedRecords[i].Values[j]; end; end; function TfrViewDetallesBase.DarPosicionCAMPO(const Nombre: String): Integer; var i: Integer; begin i:=0; while ((cxGridView.Columns[i].DataBinding.FieldName <> Nombre) and (i < cxGridView.ColumnCount)) do inc(i); if (i = cxGridView.ColumnCount) then raise Exception.Create('El campo ' + Nombre + ' no se ha encontrado en el grid (uViewDetallesBase)'); Result := i; end; procedure TfrViewDetallesBase.EndUpdate; begin if Assigned(_FocusedView) then _FocusedView.EndUpdate; end; function TfrViewDetallesBase.EsTipoEditable(AItem: TcxCustomGridTableItem): Boolean; var IndiceCol : Integer; begin Result := True; IndiceCol := cxGridView.GetColumnByFieldName(CAMPO_TIPO).Index; if (AItem.GridView.Items[IndiceCol].EditValue = TIPO_DETALLE_SALTO) then begin IndiceCol := cxGridView.GetColumnByFieldName(CAMPO_CONCEPTO).Index; if AItem.Index >= IndiceCol then Result := False end else begin if (AItem.GridView.Items[IndiceCol].EditValue = TIPO_DETALLE_SUBTOTAL) or (AItem.GridView.Items[IndiceCol].EditValue = TIPO_DETALLE_TITULO_OPCIONAL) or (AItem.GridView.Items[IndiceCol].EditValue = TIPO_DETALLE_TITULO) then begin IndiceCol := cxGridView.GetColumnByFieldName(CAMPO_CONCEPTO).Index; if AItem.Index > IndiceCol then Result := False end end; end; procedure TfrViewDetallesBase.ExpandirTodo; begin if Assigned(_FocusedView) then _FocusedView.ViewData.Expand(True); end; procedure TfrViewDetallesBase.FontEdit1Accept(Sender: TObject); begin inherited; CurrText.Assign(FontEdit1.Dialog.Font); end; procedure TfrViewDetallesBase.FontEdit1BeforeExecute(Sender: TObject); begin inherited; FontEdit1.Dialog.Font.Assign(CurEdit.SelAttributes); end; procedure TfrViewDetallesBase.FontNameChange(Sender: TObject); begin if FUpdating then Exit; CurrText.Name := FontName.Items[FontName.ItemIndex]; end; procedure TfrViewDetallesBase.FontSizeChange(Sender: TObject); begin if FUpdating then Exit; CurrText.Size := StrToInt(FontSize.Text); end; function TfrViewDetallesBase.GetController: IControllerDetallesBase; begin Result := FController; end; function TfrViewDetallesBase.GetDetalles: IDAStronglyTypedDataTable; begin Result := FDetalles; end; function TfrViewDetallesBase.GetFocusedView: TcxGridDBTableView; begin Result := cxGridView; end; function TfrViewDetallesBase.GetGrid: TcxGrid; begin Result := cxGrid; end; procedure TfrViewDetallesBase.GotoFirst; begin if Assigned(_FocusedView) then _FocusedView.DataController.GotoFirst; end; procedure TfrViewDetallesBase.GotoLast; begin if Assigned(_FocusedView) then _FocusedView.DataController.GotoLast; end; function TfrViewDetallesBase.HayQueRecalcular(AItem: TcxCustomGridTableItem): Boolean; begin Result := (AItem = cxGridViewTIPO) or (AItem = cxGridViewCANTIDAD) or (AItem = cxGridViewIMPORTEUNIDAD); end; function TfrViewDetallesBase.IsEmpty: Boolean; begin Result := (_FocusedView.ViewData.RowCount < 1); end; {procedure TfrViewDetallesBase.OnSelectChange(Sender: TObject); begin if (csDestroying in ComponentState) then Exit; try FUpdating := True; // FontSize.Text := IntToStr(CurEdit.SelAttributes.Size); // FontName.FontName := CurEdit.SelAttributes.Name; finally FUpdating := False; end; end;} procedure TfrViewDetallesBase.RestoreGridStatus; begin if Assigned(FGridStatus) and (not IsEmpty) then FGridStatus.Restore(_FocusedView); end; procedure TfrViewDetallesBase.SaveGridStatus; begin FreeAndNil(FGridStatus); if not IsEmpty then FGridStatus := TcxGridStatus.Create(_FocusedView); end; procedure TfrViewDetallesBase.SeleccionarFilaActual; begin //Quitamos lo que hubiera seleccionado cxGrid.ActiveView.DataController.ClearSelection; with cxGrid.ActiveView.DataController do if RowCount > 0 then SelectRows(GetFocusedRowIndex,GetFocusedRowIndex); end; procedure TfrViewDetallesBase.SeleccionarTodo; begin if Assigned(_FocusedView) then begin _FocusedView.Controller.SelectAll; end; end; procedure TfrViewDetallesBase.SetController(const Value: IControllerDetallesBase); var AListaValores : TStringList; AItem : TcxImageComboBoxItem; i: integer; DC: HDC; begin FController := Value; //Rellenamos los tipos de letra que tenemos FontName.Items.Clear; DC := GetDC(0); EnumFonts(DC, nil, @EnumFontsProc, Pointer(FontName.Items)); ReleaseDC(0, DC); FontName.Sorted := True; //Rellenamos los tipos de conceptos que hay if Assigned(FController) then begin AListaValores := FController.DarListaTIPOSDETALLE; with (cxGridViewTIPO.Properties as TcxImageComboBoxProperties) do if Items.Count = 0 then begin Items.BeginUpdate; try Items.Clear; for i:=0 to AListaValores.Count-1 do begin AItem := Items.Add; AItem.Tag := i; AItem.Description := AListaValores.ValueFromIndex[i]; AItem.Value := AListaValores.Names[i]; end; finally DefaultDescription := AListaValores.ValueFromIndex[0]; FreeAndNil(AListaValores); Items.EndUpdate; end; end; end; end; procedure TfrViewDetallesBase.SetDetalles(const Value: IDAStronglyTypedDataTable); begin FDetalles := Value; if Assigned(FDetalles) then DADataSource.DataTable := FDetalles.DataTable else DADataSource.DataTable := NIL; end; procedure TfrViewDetallesBase.TBXItem13Click(Sender: TObject); begin inherited; if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; end; procedure TfrViewDetallesBase.TratamientoTeclas(Key: Word; Shift: TShiftState; AItem: TcxCustomGridTableItem = nil); begin cxGridView.BeginUpdate; try case Key of VK_DOWN : begin //En el caso de ser la última fila hacemos un append nosotros no el grid //ya que se saltaria la lógica del controllerDetallesBase if cxGridView.Controller.IsFinish then begin //Key := 0; if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; actAnadir.Execute; end; //Baja los conceptos seleccionados if Shift = [ssAlt] then begin //Key := 0; actBajar.Execute; end; end; VK_UP : begin //Sube los conceptos seleccionados if Shift = [ssAlt] then begin //Key := 0; actSubir.Execute; end; end; VK_RETURN, VK_RIGHT : begin //En el caso de ser la última fila hacemos un append nosotros no el grid //ya que se saltaria la lógica del controllerDetallesBase if Assigned(AItem) and cxGridView.Controller.IsFinish and AItem.IsLast then begin //Key := 0; if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; actAnadir.Execute; end; end; end; finally cxGridView.EndUpdate; end; end; procedure TfrViewDetallesBase.actAnadirUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not ReadOnly; end; procedure TfrViewDetallesBase.actAnchoAutomaticoExecute(Sender: TObject); begin inherited; AjustarAncho end; procedure TfrViewDetallesBase.actAnchoAutomaticoUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := not IsEmpty; end; procedure TfrViewDetallesBase.actBajarExecute(Sender: TObject); begin _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.move(FDetalles, darListaSeleccionados, 1); finally _FocusedView.EndUpdate; end; end; procedure TfrViewDetallesBase.actBajarUpdate(Sender: TObject); begin inherited; if not Assigned(cxGridView.Controller.FocusedRow) then (Sender as TAction).Enabled := False else (Sender as TAction).Enabled := (not ReadOnly) and (not cxGridView.Controller.FocusedRow.IsLast) end; procedure TfrViewDetallesBase.actDetallesCopiarExecute(Sender: TObject); begin ShowHourglassCursor; try CopiarSeleccionGridAlPortapapeles(_Grid); finally HideHourglassCursor; end; end; procedure TfrViewDetallesBase.actDetallesCopiarUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := Assigned(cxGridView.Controller.FocusedRow); end; procedure TfrViewDetallesBase.actDetallesCortarExecute(Sender: TObject); begin ShowHourglassCursor; Application.ProcessMessages; try CortarSeleccionGridAlPortapapeles(_Grid); finally HideHourglassCursor; end; end; procedure TfrViewDetallesBase.actDetallesCortarUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := Assigned(cxGridView.Controller.FocusedRow) and not ReadOnly ; end; procedure TfrViewDetallesBase.actDetallesPegarExecute(Sender: TObject); begin ShowHourglassCursor; try PegarAlGridDesdePortapapeles(_Grid); finally HideHourglassCursor; end; end; procedure TfrViewDetallesBase.actDetallesPegarUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := Assigned(cxGridView.Controller.FocusedRow) and not ReadOnly and HayDatosEnPortapapeles; end; procedure TfrViewDetallesBase.actSeleccionarTodoExecute(Sender: TObject); begin inherited; SeleccionarTodo; end; procedure TfrViewDetallesBase.actSeleccionarTodoUpdate(Sender: TObject); begin inherited; (Sender as TAction).Enabled := Assigned(DADataSource.DataTable); end; procedure TfrViewDetallesBase.actSubirExecute(Sender: TObject); begin _FocusedView.BeginUpdate; try if _FocusedView.Controller.EditingController.IsEditing then _FocusedView.Controller.EditingController.Edit.PostEditValue; if Assigned(Controller) and Assigned(FDetalles) then Controller.Move(FDetalles, DarListaSeleccionados, -1); finally _FocusedView.EndUpdate; end; end; { TcxMyRichEdit } destructor TcxMyRichEdit.Destroy; begin inherited; end; procedure TcxMyRichEdit.DoPaste; begin if Assigned(FOnPaste) then FOnPaste(Self, Self.Text); end; procedure TcxMyRichEdit.FInnerRichOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if ((Shift = [ssShift]) and (Key = VK_INSERT)) then begin PasteFromClipboard; Key := 0; end; end; procedure TcxMyRichEdit.HookInnerControl; begin { Desviamos los mensajes que recibe el componente RichEdit interno de la columna a un procedimiento nuestro para interceptar los mensajes de pegar del portapapeles y así en vez de ejecutar el 'paste' por defecto de Windows, hacemos nuestro 'paste'.} FOldWndProc := InnerRich.WindowProc; InnerRich.WindowProc := InnerControlWindowProc; InnerRich.OnKeyDown := FInnerRichOnKeyDown; // InnerRich.PopupMenu := ; end; procedure TcxMyRichEdit.Initialize; begin inherited; if Assigned(InnerRich) then HookInnerControl; end; procedure TcxMyRichEdit.InnerControlWindowProc(var Message: TMessage); begin case Message.msg of WM_PASTE: if not _FPegando then PasteFromClipboard; else FOldWndProc(Message); end; end; procedure TcxMyRichEdit.PasteFromClipboard; begin _FPegando := True; try //if HayDatosEnPortapapeles(CF_FACTUGES) then PegarAlGridDesdePortapapeles(FGrid); //else //inherited; DoPaste; finally _FPegando := False; end; end; { TcxMyRichEditProperties } class function TcxMyRichEditProperties.GetContainerClass: TcxContainerClass; begin Result := TcxMyRichEdit; end; initialization _FRecalculando := False; _FRecalcular := False; _FPegando := False; end.