Programujete v PowerBuilderu?

1. 2. 1998

Sdílet

Zkuste PFCtool 5.6! Americká firma PowerCerv poskytuje vývojové nástroje, jejichž cílem je pomáhat při vytvá...


Zkuste PFCtool 5.6!



Americká firma PowerCerv poskytuje vývojové nástroje, jejichž cílem je pomáhat při vytváření a správě velkých, na trh klient/server zaměřených aplikací (a také aplikací internetovských). Těmito svými nástroji se převážně orientuje na vývojové prostředky PowerBuilder a C++, které je možno používat na většině běžně
dostupných operačních systémech, a podporuje relační databáze jako např. Sybase (včetně SQL Anywhere), Oracle, Microsoft SQL Server. Mezi produkty firmy PowerCerv patří PowerTOOL - objektové knihovny pro PowerBuilder zahrnující
šablony, okna, komponenty a funkce, PADLock - nástroje pro PowerBuilder sloužící k zabezpečení aplikací, dále FLOWBuilder, pomocí kterého mohou vývojáři do klient/server aplikací zabudovat tzv. workflow nástroje či AppSync, umožňující úpravu aplikací pro použití v heterogenních prostředích.

Dalším produktem firmy PowerCerv, jemuž se budeme blížeji věnovat, je objektová
knihovna PFCtool pro PowerBuilder Foundation Class Library. Protože PowerBuilder
patří mezi nejpoužívanější vývojové nástroje určené k tvorbě velkých, převážně
databázových aplikací i v našich krajích, mohly by komponenty PFCtool oslovit i naše vývojové pracovníky. PFCtool poskytuje jednoduše použitelnou knihovnu
užitečných objektů, komponent a šablon, které významným způsobem rozšiřují
funkcionalitu nativní knihovny PFC PowerBuilderu. Hlavním účelem tohoto produktu je zrychlení vývoje aplikací, jejich lepší údržba, snadnější ladění aplikace a snížení chybovosti.

PFCtool obsahuje čtyři knihovny: Pfctoolm.pbl a Pfctoole.pbl (obsahují základní
aplikační a nevizuální objekty), Pfctsamp.pbl a Parmwzrd.pbl potom obsahují
objekty ukázkové aplikace. Mimochodem, ukázková aplikace je velmi dobře provedena a neukazuje jen možnosti použití PFCtool, nýbrž i interaktivní
popis jednotlivých objektů (např. popis parametrů, jednotlivé události, vkládání
funkcí apod.). K dispozici je navíc tzv. PFCtool Parameter Wizard, což je samostatná aplikace určená k automatickému generování skriptů; tento postup zrychluje vývojářskou práci a pomáhá eliminovat potenciální chyby. Objekty
PFCtool jsou - díky objektovému charakteru PowerBuilderu - odvozeny z knihovny PFC, a proto aplikace, která tyto objekty využívá, musí mít nadefinovány
určité PFC knihovny (pfemain.pbl, pfcmain.pbl, pfeapsrv.pbl, pfcapsrv.pbl,
pfewnsrv.pbl, pfcwnsrv.pbl, pfedwsrv.pbl, pfcdwsrv.pbl) v tzv. library search path.

Objekty PFCtool lze rozdělit zhruba do tří skupin: Objekty sloužící k tvorbě datových oken (Data Windows), objekty ke tvorbě nabídek a uživatelské objekty (Attribute Objects, Service Objects, Standard User Objects). Objekty určené k tvorbě datových oken jsou odvozené od PowerBuilder Foundation Class Library
objektů w_master, w_splash či w_frame, všechny PFCtool šablony pak od tzv. w_pcva (Base Window Ancestor extension layer); objekty sloužící ke tvorbě nabídek jsou odvozené od PFC objektů m_frame či m_master. Technologie, kterou PowerCerv u objektů používá, je tzv. Run-time Configurable Objects (RCO), což
znamená dynamické chování a konfiguraci objektů. Jako příklad použití šablony datových oken si uvedeme tzv. šablonu UDI - Update, Delete, Insert (pcv_w_udi), jež najde uplatnění při základní práci s údaji databázových tabulek: Jednoduchou
prezentaci údajů tabulky (datové okno odvozené z PFCtool objektu u_dwa) s možnostmi aktualizace, vkládání a mazání záznamů tabulky prostřednictvím tlačítek ovládacího panelu (PFCtool objekt m_pcva_udi). Pokud není třeba složitějšího chování, není zapotřebí psát žádný dodatečný kód. Samozřejmě v případě speciálnějších požadavků je možno chování příslušně upravit.

K dispozici je pochopitelně i obsáhlá elektronická nápověda, jednou ve standardní podobě nápovědy pro Windows, podruhé ve formátu Adobe Readeru.
Knihovny PCtools tak poskytují velmi silný a užitečný nástroj pro všechny, kteří vyvíjejí své aplikace v programu PowerBuilder.




Autor článku

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }